C#笔记:RC6算法实现

2019-11-22 09:45:58 浏览数 (1)

代码语言:javascript复制
public class RC6Cryptor
    {
        public byte[] Encrypt(byte[] data, string pwd)
        {
            SymmetricAlgorithm sa = Rc6.Create();
            //
            byte[] inputByteArray = data;//得到需要加密的字节数组
            //设置密钥及密钥向量
            sa.Key = Encoding.UTF8.GetBytes(pwd);
            sa.IV = null;
            byte[] cipherBytes = null;
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, sa.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    cipherBytes = ms.ToArray();//得到加密后的字节数组
                }
            }
            
            return cipherBytes;
        }

        public byte[] Decrypt(byte[] data, string pwd)
        {           
            SymmetricAlgorithm sa = Rc6.Create();           
            byte[] inputByteArray = data;//得到需要加密的字节数组   
            //设置密钥及密钥向量
            sa.Key = Encoding.UTF8.GetBytes(pwd);
            sa.IV = null;
            byte[] textBytes = null;
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, sa.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    textBytes = ms.ToArray();//得到加密后的字节数组
                }
            }
            
            return textBytes;
        }
    }
    
    public class Rc6 : SymmetricAlgorithm
    {
        public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
        {
            var tempCrytor = new RC6Transform(rgbKey);
            tempCrytor.Type = "dec";
            return tempCrytor;
        }

        public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
        {
            var tempCrytor = new RC6Transform(rgbKey);
            tempCrytor.Type = "enc";
            return tempCrytor;
        }

        public override void GenerateIV()
        {
            //do nothing
        }

        public override byte[] Key
        {
            get
            {
                return this.KeyValue;
            }
            set
            {
                var key = padding(value, 32);
                this.KeyValue = key;
            }
        }

        public override byte[] IV
        {
            get
            {
                return new byte[1];
            }
            set
            {
                if (value != null && value.Length > 1)
                    throw new CryptographicException("RC6 doesn't use an Initialization Vector.");
            }
        }

        private byte[] padding(byte[] inputBuffer, int BlockSize)
        {
            if (BlockSize > 255)
            {
                throw new CryptographicException("The blocksize can not be greater than 255");
            }

            int count = 0;
            if (inputBuffer.Length == 0)
            {
                count = BlockSize;
            }
            else if (inputBuffer.Length % BlockSize == 0)
            {
                return inputBuffer;
            }
            else
            {
                count = BlockSize - inputBuffer.Length % BlockSize;
            }

            byte[] ret = new byte[inputBuffer.Length   count];
            for (int i = 0; i < inputBuffer.Length; i  )
            {
                ret[i] = (byte)inputBuffer[i];
            }
            for (int i = inputBuffer.Length; i < ret.Length; i  )
            {
                ret[i] = (byte)count;
            }
            return ret;
        }

        public override void GenerateKey()
        {
            // doNothing
        }
        public static new Rc6 Create()
        {
            return new Rc6();
        }
    }

    public class RC6Transform : ICryptoTransform
    {
        private const int w = 32;
        private const int b = 16;                   //16,24,32
        private const int r = 20;
        private const uint P32 = 0xB7E15163;
        private const uint Q32 = 0x9E3779B9;
        private const int bytes = w / 8;
        private const int c = (b   bytes - 1) / bytes;
        private const int R24 = 2 * r   4;
        private const int lgw = 5;
        private uint[] S;
        private int keyLen;
        public string Type;

        public RC6Transform(byte[] key)
        {
            int Round = 32;
            //Round = 16;
            //Round = 24;
            this.S = new uint[Round * 8];    //选择加密方式128位,192位,256位
            this.keyLen = Round;
            char[] _key = this.key(key);
            this.setup(_key, this.keyLen); //setup(_key, 16);初始化,将私密与系统密钥混合
        }


        public bool CanReuseTransform
        {
            get { return true; }
        }

        public bool CanTransformMultipleBlocks
        {
            get { return true; }
        }

        public int InputBlockSize
        {
            get { return 16; }
        }

        public int OutputBlockSize
        {
            get { return 16; }
        }

        public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
        {
            if (this.Type == "enc")
            {
                int length = inputCount;
                byte[] orgCopy = new byte[length];
                Array.Copy(inputBuffer, inputOffset, orgCopy, 0, length);

                orgCopy = this.EncryptBuffer(orgCopy);

                Array.Copy(orgCopy, 0, outputBuffer, 0, length);
                return length;
            }
            else
            {
                int length = inputOffset   inputCount;
                byte[] orgCopy = new byte[inputCount];
                Array.Copy(inputBuffer, inputOffset, orgCopy, 0, inputCount);
                orgCopy = this.DecryptBuffer(orgCopy);

                length = length - IsPadding(orgCopy);

                Array.Copy(orgCopy, 0, outputBuffer, outputOffset, length);
                return length;
            }
        }
        private int IsPadding(byte[] orgCopy)
        {
            int count = orgCopy[orgCopy.Length - 1];

            if (count <= 255)
            {
                for (int i = orgCopy.Length - 1, j = 0; j < count; i--, j  )
                {
                    if (orgCopy[i] != count)
                    {
                        return 0;
                    }
                }
            }
            else
            {
                return 0;
            }
            return count;
        }
        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
        {
            int length = inputCount;
            if (inputCount == 0) return new byte[0];
            byte[] ret = padding(inputBuffer, InputBlockSize, inputCount);
            ret = this.EncryptBuffer(ret);
            return ret;
        }

        private byte[] padding(byte[] inputBuffer, int BlockSize, int inputCount)
        {
            int count = BlockSize - inputCount;

            byte[] ret = new byte[inputCount   count];
            for (int i = 0; i < inputCount; i  )
            {
                ret[i] = (byte)inputBuffer[i];
            }
            for (int i = inputCount; i < ret.Length; i  )
            {
                ret[i] = (byte)count;
            }
            return ret;
        }

        public void Dispose()
        {
            try
            {
                GC.SuppressFinalize(this);
            }
            catch { }
        }

        private uint ROTL(uint x, uint y) { return ((x << (int)(y & (w - 1))) | (x >> (int)(w - (y & (w - 1))))); }
        private uint ROTR(uint x, uint y) { return ((x >> (int)(y & (w - 1))) | (x << (int)(w - (y & (w - 1))))); }
        public char[] key(byte[] key)
        {
            // pwd = (pwd.Length % 16 != 0 ? pwd.PadRight(pwd.Length   (16 - (pwd.Length % 16)), ' ') : pwd);   
            //这里必须保证加密私密的密码长为为16,不足加空隔满足长度需要
            byte[] asciiBytes = Encoding.Convert(Encoding.UTF8, Encoding.ASCII, key);
            char[] asciiChars = new char[Encoding.ASCII.GetCharCount(asciiBytes, 0, asciiBytes.Length)];
            Encoding.ASCII.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0);
            return asciiChars;
        }
        /// <summary>
        /// 初始化并混合用户密钥
        /// </summary>
        /// <param name="K"></param>
        /// <param name="b"></param>
        public void setup(char[] K, int b)
        {
            int i, j, s, v;
            uint[] L = new uint[b]; /* Big enough for max b */
            uint A, B;
            L[b - 1] = 0;
            for (i = 15 - 1; i >= 0; i--)
                L[i / bytes] = (L[i / bytes] << 8)   K[i];
            S[0] = P32;
            unchecked
            {
                for (i = 1; i <= 2 * r   3; i  )
                    S[i] = S[i - 1]   Q32;
            }
            A = B = 0;
            i = j = 0;
            v = R24;
            if (c > v) v = c;
            v *= 3;
            unchecked
            {
                for (s = 1; s <= v; s  )
                {
                    A = S[i] = ROTL(S[i]   A   B, 3);
                    B = L[j] = ROTL(L[j]   A   B, A   B);
                    i = (i   1) % R24;
                    j = (j   1) % c;
                }
            }
        }
        public byte[] EncryptBuffer(byte[] buffer)
        {
            int UpperBound = buffer.Length - 15;
            for (int i = 0; i < UpperBound; i  = 16)
            {
                uint A = BitConverter.ToUInt32(buffer, i);
                uint B = BitConverter.ToUInt32(buffer, i   4);
                uint C = BitConverter.ToUInt32(buffer, i   8);
                uint D = BitConverter.ToUInt32(buffer, i   12);
                unchecked
                {
                    B  = S[0];
                    D  = S[1];
                    for (int j = 2; j <= 2 * r; j  = 2)
                    {
                        uint t = ROTL(B * (2 * B   1), lgw);
                        uint u = ROTL(D * (2 * D   1), lgw);
                        A = ROTL(A ^ t, u)   S[j];
                        C = ROTL(C ^ u, t)   S[j   1];
                        uint x = A;
                        A = B;
                        B = C;
                        C = D;
                        D = x;
                    }
                    A  = S[2 * r   2];
                    C  = S[2 * r   3];
                }
                BitConverter.GetBytes(A).CopyTo(buffer, i);
                BitConverter.GetBytes(B).CopyTo(buffer, i   4);
                BitConverter.GetBytes(C).CopyTo(buffer, i   8);
                BitConverter.GetBytes(D).CopyTo(buffer, i   12);
            }
            return buffer;
        }
        public byte[] DecryptBuffer(byte[] buffer)
        {
            int UpperBound = buffer.Length - 15;
            for (int i = 0; i < UpperBound; i  = 16)
            {
                uint A = BitConverter.ToUInt32(buffer, i);
                uint B = BitConverter.ToUInt32(buffer, i   4);
                uint C = BitConverter.ToUInt32(buffer, i   8);
                uint D = BitConverter.ToUInt32(buffer, i   12);
                unchecked
                {
                    C -= S[2 * r   3];
                    A -= S[2 * r   2];
                    for (int j = 2 * r; j >= 2; j -= 2)
                    {
                        uint x = D;
                        D = C;
                        C = B;
                        B = A;
                        A = x;
                        uint u = ROTL(D * (2 * D   1), lgw);
                        uint t = ROTL(B * (2 * B   1), lgw);
                        C = ROTR(C - S[j   1], t) ^ u;
                        A = ROTR(A - S[j], u) ^ t;
                    }
                    D -= S[1];
                    B -= S[0];
                }
                BitConverter.GetBytes(A).CopyTo(buffer, i);
                BitConverter.GetBytes(B).CopyTo(buffer, i   4);
                BitConverter.GetBytes(C).CopyTo(buffer, i   8);
                BitConverter.GetBytes(D).CopyTo(buffer, i   12);
            }
            return buffer;
        }

    }

0 人点赞