前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C#笔记:RC6算法实现

C#笔记:RC6算法实现

作者头像
超级大猪
发布2019-11-22 09:45:58
1.2K0
发布2019-11-22 09:45:58
举报
文章被收录于专栏:大猪的笔记大猪的笔记
代码语言: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;
        }

    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-02-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档