C#笔记:RC4算法实现 public class RC4Cryptor { public byte[] Encrypt(byte[] data, string pwd) { SymmetricAlgorithm sa = RC4Creator.Create(); ; // byte[] inputByteArray = data;//得到需要加密的字节数组 //设置密钥及密钥向量 sa.Key = Encoding.UTF8.GetBytes(pwd); sa.IV = null; MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, sa.CreateEncryptor(), CryptoStreamMode.Write); cs.Write(inputByteArray, 0, inputByteArray.Length); cs.FlushFinalBlock(); byte[] cipherBytes = ms.ToArray();//得到加密后的字节数组 cs.Close(); ms.Close(); return cipherBytes; } public byte[] Decrypt(byte[] data, string pwd) { SymmetricAlgorithm sa = RC4Creator.Create(); //BLL.RC4.Create(); byte[] inputByteArray = data;//得到需要加密的字节数组 //设置密钥及密钥向量 sa.Key = Encoding.UTF8.GetBytes(pwd); sa.IV = null; MemoryStream ms = new MemoryStream(); CryptoStream cs = new CryptoStream(ms, sa.CreateDecryptor(), CryptoStreamMode.Write); cs.Write(inputByteArray, 0, inputByteArray.Length); cs.FlushFinalBlock(); byte[] textBytes = ms.ToArray();//得到加密后的字节数组 cs.Close(); ms.Close(); return textBytes; } } public class RC4 : SymmetricAlgorithm { /// <summary> /// Initializes a new instance of the RC4 class. /// </summary> /// <remarks> /// The default keysize is 128 bits. /// </remarks> public RC4() { this.KeySizeValue = 128; } public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV) { throw new NotImplementedException(); } public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV) { throw new NotImplementedException(); } /// <summary> /// Gets or sets the block size of the cryptographic operation in bits. /// </summary> /// <value>The block size of RC4 is always 8 bits.</value> /// <exception cref="CryptographicException">The block size is invalid.</exception> public override int BlockSize { get { return 8; } set { if (value != 8 && value != 0) throw new CryptographicException("RC4 is a stream cipher, not a block cipher."); } } /// <summary> /// Gets or sets the feedback size of the cryptographic operation in bits. /// </summary> /// <value>This property always throws a <see cref="CryptographicException"/>.</value> /// <exception cref="CryptographicException">This exception is always thrown.</exception> /// <remarks>RC4 doesn't use the FeedbackSize property.</remarks> public override int FeedbackSize { get { throw new CryptographicException("RC4 doesn't use the feedback size property."); } set { throw new CryptographicException("RC4 doesn't use the feedback size property."); } } /// <summary> /// Gets or sets the initialization vector (IV) for the symmetric algorithm. /// </summary> /// <value>This property always returns a byte array of length one. The value of the byte in the array is always set to zero.</value> /// <exception cref="CryptographicException">An attempt is made to set the IV to an invalid instance.</exception> /// <remarks>RC4 doesn't use the IV property, however the property accepts IV's of up to one byte (RC4's <see cref="BlockSize"/>) in order to interoperate with software that has been written with the use of block ciphers in mind.</remarks> public override byte[] IV { get { return new byte[1]; } set { if (value != null && value.Length > 1) throw new CryptographicException("RC4 doesn't use an Initialization Vector."); } } /// <summary> /// Gets the block sizes that are supported by the symmetric algorithm. /// </summary> /// <value>An array containing the block sizes supported by the algorithm.</value> /// <remarks>Only a block size of one byte is supported by the RC4 algorithm.</remarks> public override KeySizes[] LegalBlockSizes { get { return new KeySizes[] { new KeySizes(8, 8, 0) }; } } /// <summary> /// Gets the key sizes that are supported by the symmetric algorithm. /// </summary> /// <value>An array containing the key sizes supported by the algorithm.</value> /// <remarks>Only key sizes that match an entry in this array are supported by the symmetric algorithm.</remarks> public override KeySizes[] LegalKeySizes { get { return new KeySizes[] { new KeySizes(8, 2048, 8) }; } } /// <summary> /// Gets or sets the mode for operation of the symmetric algorithm. /// </summary> /// <value>The mode for operation of the symmetric algorithm.</value> /// <remarks>RC4 only supports the OFB cipher mode. See <see cref="CipherMode"/> for a description of this mode.</remarks> /// <exception cref="CryptographicException">The cipher mode is not OFB.</exception> public override CipherMode Mode { get { return CipherMode.OFB; } set { if (value != CipherMode.OFB) throw new CryptographicException("RC4 only supports OFB."); } } /// <summary> /// Gets or sets the padding mode used in the symmetric algorithm. /// </summary> /// <value>The padding mode used in the symmetric algorithm. This property always returns PaddingMode.None.</value> /// <exception cref="CryptographicException">The padding mode is set to a padding mode other than PaddingMode.None.</exception> public override PaddingMode Padding { get { return PaddingMode.None; } set { if (value != PaddingMode.None) throw new CryptographicException("RC4 is a stream cipher, not a block cipher."); } } /// <summary> /// This is a stub method. /// </summary> /// <remarks>Since the RC4 cipher doesn't use an Initialization Vector, this method will not do anything.</remarks> public override void GenerateIV() { // do nothing } /// <summary> /// Generates a random Key to be used for the algorithm. /// </summary> /// <remarks>Use this method to generate a random key when none is specified.</remarks> public override void GenerateKey() { byte[] key = new byte[this.KeySize / 8]; GetRNGCSP().GetBytes(key); this.Key = key; } /// <summary> /// Creates an instance of the default cryptographic object used to perform the RC4 transformation. /// </summary> /// <returns>The instance of a cryptographic object used to perform the RC4 transformation.</returns> public static new RC4 Create() { return Create("ARCFOUR"); } /// <summary> /// Creates an instance of the specified cryptographic object used to perform the RC4 transformation. /// </summary> /// <param name="AlgName">The name of the specific implementation of <see cref="RC4"/> to create.</param> /// <returns>A cryptographic object.</returns> public static new RC4 Create(string AlgName) { try { //if (AlgName.ToUpper() == "RC4" || AlgName.ToLower() == "org.mentalis.security.cryptography.rc4cryptoserviceprovider") // return new RC4CryptoServiceProvider(); //else if (AlgName.ToUpper() == "ARCFOUR" || AlgName.ToLower() == "org.mentalis.security.cryptography.arcfourmanaged") // return new ARCFourManaged(); return new RC4Creator(); } catch { } return null; } /// <summary> /// Returns an <see cref="RNGCryptoServiceProvider"/> instance. /// </summary> /// <returns>An RNGCryptoServiceProvider instance.</returns> protected RNGCryptoServiceProvider GetRNGCSP() { if (m_RNG == null) m_RNG = new RNGCryptoServiceProvider(); return m_RNG; } /// <summary> /// Holds the RNGCryptoServiceProvider object. /// </summary> private RNGCryptoServiceProvider m_RNG; } public class RC4Creator : RC4 { public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV) { if (m_IsDisposed) throw new ObjectDisposedException(this.GetType().FullName); if (rgbKey == null) throw new ArgumentNullException("Key is a null reference."); if (rgbKey.Length == 0 || rgbKey.Length > 256) throw new CryptographicException("Invalid Key."); if (rgbIV != null && rgbIV.Length > 1) throw new CryptographicException("Invalid Initialization Vector."); return new RC4CryptTransForm(rgbKey); } public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV) { return CreateDecryptor(rgbKey, rgbIV); ; } public override void GenerateIV() { //do nothing; } public override void GenerateKey() { } protected override void Dispose(bool disposing) { base.Dispose(true); m_IsDisposed = true; } private bool m_IsDisposed; } public class RC4CryptTransForm : ICryptoTransform { byte[] m_Key; int m_KeyLen; byte[] m_Permutation; bool m_Disposed; byte m_Index1; byte m_Index2; public RC4CryptTransForm(byte[] key) { m_Key = (byte[])key.Clone(); m_KeyLen = key.Length; m_Permutation = new byte[256]; m_Disposed = false; Init(); } private void Init() { byte temp; // init state variable for (int i = 0; i < 256; i++) { m_Permutation[i] = (byte)i; } m_Index1 = 0; m_Index2 = 0; // randomize, using key for (int j = 0, i = 0; i < 256; i++) { j = (j + m_Permutation[i] + m_Key[i % m_KeyLen]) % 256; // swap m_State.permutation[i] and m_State.permutation[j] temp = m_Permutation[i]; m_Permutation[i] = m_Permutation[j]; m_Permutation[j] = temp; } } public bool CanReuseTransform { get { return true; } } public bool CanTransformMultipleBlocks { get { return true; } } public int InputBlockSize { get { return 1; } } public int OutputBlockSize { get { return 1; } } public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); if (inputBuffer == null || outputBuffer == null) throw new ArgumentNullException(); if (inputOffset < 0 || outputOffset < 0 || inputOffset + inputCount > inputBuffer.Length || outputOffset + inputCount > outputBuffer.Length) throw new ArgumentOutOfRangeException(); byte j, temp; int length = inputOffset + inputCount; for (; inputOffset < length; inputOffset++, outputOffset++) { // update indices m_Index1 = (byte)((m_Index1 + 1) % 256); m_Index2 = (byte)((m_Index2 + m_Permutation[m_Index1]) % 256); // swap m_State.permutation[m_State.index1] and m_State.permutation[m_State.index2] temp = m_Permutation[m_Index1]; m_Permutation[m_Index1] = m_Permutation[m_Index2]; m_Permutation[m_Index2] = temp; // transform byte j = (byte)((m_Permutation[m_Index1] + m_Permutation[m_Index2]) % 256); outputBuffer[outputOffset] = (byte)(inputBuffer[inputOffset] ^ m_Permutation[j]); } return inputCount; } public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { if (m_Disposed) throw new ObjectDisposedException(this.GetType().FullName); byte[] ret = new byte[inputCount]; TransformBlock(inputBuffer, inputOffset, inputCount, ret, 0); Init(); return ret; } public void Dispose() { Array.Clear(m_Key, 0, m_Key.Length); Array.Clear(m_Permutation, 0, m_Permutation.Length); m_Index1 = 0; m_Index2 = 0; m_Disposed = true; try { GC.SuppressFinalize(this); } catch { } } } 来自 yzh 写于 2014-05-04 21:40 -- 更新于2020-10-19 13:06 -- 0 条评论