C#笔记:RC4算法实现

2019-11-21 16:54:25 浏览数 (1)

代码语言:javascript复制
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 { }
        }
    }

0 人点赞