最近帮一个网友解决RC4加减密的问题,虽说在网上有类似的问题,但是对于中文解决不是很理想,因此我在别人的基础上进行修改,并且为了方便显示,把加密后的字符串用16进制来显示。
大致的代码如下:
//-------------------------- RC4 encrypt class ------------------------------------
//---------------------------------------------------------------------------------
//---File: clsRC4Engine
//---Description: The encrypt class file using RC4
//---Author: Knight
//---Date: Jul.3, 2006
//---------------------------------------------------------------------------------
//--------------------------{RC4 encrypt class}-------------------------------------
namespace CryptoRC4
{
using System;
using System.Text;
/// <summary>
/// Summary description for clsRC4Engine.
/// </summary>
public class clsRC4Engine
{
private static long m_nBoxLen = 255;
/// <summary>
/// Avoid this class to be inited
/// </summary>
protected clsRC4Engine()
{
//
// TODO: Add constructor logic here
//
}
private static void GetKeyBytes( string Key, out byte[] m_nBox )
{
//
// Used to populate m_nBox
//
long index2 = 0;
m_nBox = new byte[m_nBoxLen];
//
// Create two different encoding
//
Encoding ascii = Encoding.ASCII;
Encoding unicode = Encoding.Unicode;
//
// Perform the conversion of the encryption key from unicode to ansi
//
byte[] asciiBytes = Encoding.Convert(unicode,ascii,
unicode.GetBytes( Key ));
//
// Convert the new byte[] into a char[] and then to string
//
char[] asciiChars = new char[ascii.GetCharCount(asciiBytes,0,asciiBytes.Length)];
ascii.GetChars(asciiBytes,0,asciiBytes.Length,asciiChars,0);
//this.m_sEncryptionKeyAscii = new string(asciiChars);
//
// Populate m_nBox
//
long KeyLen = Key.Length;
//
// First Loop
//
for ( long count = 0; count < m_nBoxLen ; count ++ )
{
m_nBox[count] = (byte)count;
}
//
// Second Loop
//
for ( long count = 0; count < m_nBoxLen ; count ++ )
{
index2 = (index2 + m_nBox[count] + asciiChars[ count % KeyLen ]) % m_nBoxLen;
byte temp = m_nBox[count];
m_nBox[count] = m_nBox[index2];
m_nBox[index2] = temp;
}
}
/// <summary>
/// Get encrypted bytes
/// </summary>
/// <param name="sData"></param>
/// <param name="m_nBox"></param>
/// <param name="EncryptedBytes"></param>
/// <returns></returns>
private static bool GetEncryptBytes( string sData, byte[] m_nBox,
out byte[] EncryptedBytes )
{
EncryptedBytes = null;
bool toRet = true;
try
{
//
// indexes used below
//
long i=0;
long j=0;
//
// Put input string in temporary byte array
//
Encoding enc_default = Encoding.Unicode;
byte[] input = enc_default.GetBytes( sData );
//
// Output byte array
//
EncryptedBytes = new byte[input.Length];
//
// Local copy of m_nBoxLen
//
byte[] n_LocBox = new byte[m_nBoxLen];
m_nBox.CopyTo(n_LocBox,0);
//
// Len of Chipher
//
long ChipherLen = input.Length + 1;
//
// Run Alghoritm
//
for ( long offset = 0; offset < input.Length ; offset++ )
{
i = ( i + 1 ) % m_nBoxLen;
j = ( j + n_LocBox[i] ) % m_nBoxLen;
byte temp = n_LocBox[i];
n_LocBox[i] = n_LocBox[j];
n_LocBox[j] = temp;
byte a = input[offset];
byte b = n_LocBox[(n_LocBox[i]+n_LocBox[j])% m_nBoxLen];
EncryptedBytes[offset] = (byte)((int)a^(int)b);
}
}
catch
{
EncryptedBytes = null;
//
// error occured - set retcode to false.
//
toRet = false;
}
return toRet;
}
/// <summary>
/// Encrypt data through specific key value
/// </summary>
/// <param name="sData"></param>
/// <param name="Key"></param>
/// <param name="EncryptedString"></param>
/// <returns></returns>
public static bool Encrypt( string sData, string Key, out string EncryptedString )
{
EncryptedString = null;
if( sData == null || Key == null ) return false;
byte[] m_nBox;
GetKeyBytes( Key, out m_nBox );
byte[] output;
if( GetEncryptBytes( sData, m_nBox, out output ) )
{
// Convert data to hex-data
EncryptedString = "";
for( int i = 0; i < output.Length; i++ )
EncryptedString += output[i].ToString( "X2" );
return true;
}
else
return false;
}
/// <summary>
/// Decrypt data using specific key
/// </summary>
/// <param name="EncryptedString"></param>
/// <param name="Key"></param>
/// <param name="sData"></param>
/// <returns></returns>
public static bool Decrypt( string EncryptedString, string Key, out string sData )
{
sData = null;
if( EncryptedString == null || Key == null ) return false;
else if( EncryptedString.Length % 2 != 0 ) return false;
byte[] m_nBox;
GetKeyBytes( Key, out m_nBox );
// Convert data from hex-data to string
byte[] bData = new byte[EncryptedString.Length / 2];
for( int i = 0; i < bData.Length; i++ )
bData[i] = Convert.ToByte( EncryptedString.Substring( i * 2, 2 ), 16 );
EncryptedString = Encoding.Unicode.GetString( bData );
byte[] output;
if( GetEncryptBytes( EncryptedString, m_nBox, out output ) )
{
sData = Encoding.Unicode.GetString( output );
return true;
}
else
return false;
}
}
}
调用如下:
//Encrypt data
string strEncryptedString;
if( clsRC4Engine.Encrypt( strValue, strKey, out strEncryptedString ) )
MessageBox.Show( strEncryptedString );
//Decrypt data
string strDecryptedString;
if( clsRC4Engine.Decrypt( strValue, strKey, out strDecryptedString ) )
MessageBox.Show( strDecryptedString );