精易论坛

标题: TEA加密解密工具类 [打印本页]

作者: hnzrb    时间: 2018-7-21 15:39
标题: TEA加密解密工具类
/// <summary>
    /// TEA加密解密工具类
    /// </summary>
    internal class TEAUtil
    {
        /// <summary>
        /// 加密解密消息包的工具类.
        /// </summary>
        private static void code(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos, byte[] key)
        {
            if (outPos > 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    In[outOffset + outPos + i] = (byte)(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i - 8]);
                }
            }
            uint[] formattedKey = FormatKey(key);
            uint y = ConvertByteArrayToUInt(In, outOffset + outPos);
            uint z = ConvertByteArrayToUInt(In, outOffset + outPos + 4);
            uint sum = 0;
            uint delta = 0x9e3779b9;
            uint n = 16;
            while (n-- > 0)
            {
                sum += delta;
                y += ((z << 4) + formattedKey[0]) ^ (z + sum) ^ ((z >> 5) + formattedKey[1]);
                z += ((y << 4) + formattedKey[2]) ^ (y + sum) ^ ((y >> 5) + formattedKey[3]);
            }
            Array.Copy(ConvertUIntToByteArray(y), 0, Out, outOffset + outPos, 4);
            Array.Copy(ConvertUIntToByteArray(z), 0, Out, outOffset + outPos + 4, 4);
            if (inPos > 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    Out[outOffset + outPos + i] = (byte)(Out[outOffset + outPos + i] ^ In[inOffset + inPos + i - 8]);
                }
            }
        }
        private static void decode(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos, byte[] key)
        {
            if (outPos > 0)
            {
                for (int i = 0; i < 8; i++)
                {
                    Out[outOffset + outPos + i] = (byte)(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i - 8]);
                }
            }
            else
            {
                Array.Copy(In, inOffset, Out, outOffset, 8);
            }
            uint[] formattedKey = FormatKey(key);
            uint y = ConvertByteArrayToUInt(Out, outOffset + outPos);
            uint z = ConvertByteArrayToUInt(Out, outOffset + outPos + 4);
            uint sum = 0xE3779B90;
            uint delta = 0x9e3779b9;
            uint n = 16;
            while (n-- > 0)
            {
                z -= ((y << 4) + formattedKey[2]) ^ (y + sum) ^ ((y >> 5) + formattedKey[3]);
                y -= ((z << 4) + formattedKey[0]) ^ (z + sum) ^ ((z >> 5) + formattedKey[1]);
                sum -= delta;
            }
            Array.Copy(ConvertUIntToByteArray(y), 0, Out, outOffset + outPos, 4);
            Array.Copy(ConvertUIntToByteArray(z), 0, Out, outOffset + outPos + 4, 4);
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="input">需要被解密的密文</param>
        /// <param name="key">密钥</param>
        /// <returns>Message 已解密的消息</returns>
        public static byte[] Decrypt(byte[] input, byte[] key)
        {
            return Decrypt(input, 0, input.Length, key);
        }
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="input">需要加密的明文</param>
        /// <param name="key">密钥</param>
        /// <returns>Message 密文</returns>
        public static byte[] Encrypt(byte[] input, byte[] key)
        {
            return Encrypt(input, 0, input.Length, key);
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="In">密文</param>
        /// <param name="offset">密文开始的位置</param>
        /// <param name="len">密文长度</param>
        /// <param name="key">密钥</param>
        /// <returns>返回明文</returns>
        public static byte[] Decrypt(byte[] In, int offset, int len, byte[] key)
        {
            // 因为QQ消息加密之后至少是16字节,并且肯定是8的倍数,这里检查这种情况
            if ((len % 8 != 0) || (len < 16))
            {
                return null;
            }
            byte[] Out = new byte[len];
            for (int i = 0; i < len; i += 8)
            {
                decode(In, offset, i, Out, 0, i, key);
            }
            for (int i = 8; i < len; i++)
            {
                Out[i] = (byte)(Out[i] ^ In[offset + i - 8]);
            }
            int pos = Out[0] & 0x07;
            len = len - pos - 10;
            byte[] res = new byte[len];
            Array.Copy(Out, pos + 3, res, 0, len);
            return res;
        }
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="In">明文</param>
        /// <param name="offset">明文开始的位置</param>
        /// <param name="len">明文长度</param>
        /// <param name="key">密钥</param>
        /// <returns>返回密文</returns>
        public static byte[] Encrypt(byte[] In, int offset, int len, byte[] key)
        {
            Random rand = new Random();
            // 计算头部填充字节数
            int pos = (len + 10) % 8;
            if (pos != 0)
            {
                pos = 8 - pos;
            }
            byte[] plain = new byte[len + pos + 10];
            plain[0] = (byte)((rand.Next() & 0xF8) | pos);
            for (int i = 1; i < pos + 3; i++)
            {
                plain[i] = (byte)(rand.Next() & 0xFF);
            }
            Array.Copy(In, 0, plain, pos + 3, len);
            for (int i = pos + 3 + len; i < plain.Length; i++)
            {
                plain[i] = 0x0;
            }
            // 定义输出流
            byte[] outer = new byte[len + pos + 10];
            for (int i = 0; i < outer.Length; i += 8)
            {
                code(plain, 0, i, outer, 0, i, key);
            }
            return outer;
        }
        //格式化密钥
        private static uint[] FormatKey(byte[] key)
        {
            if (key.Length == 0)
            {
                throw new ArgumentException("Key must be between 1 and 16 characters in length");
            }
            byte[] refineKey = new byte[16];
            if (key.Length < 16)
            {
                Array.Copy(key, 0, refineKey, 0, key.Length);
                for (int k = key.Length; k < 16; k++)
                {
                    refineKey[k] = 0x20;
                }
            }
            else
            {
                Array.Copy(key, 0, refineKey, 0, 16);
            }
            uint[] formattedKey = new uint[4];
            int j = 0;
            for (int i = 0; i < refineKey.Length; i += 4)
            {
                formattedKey[j++] = ConvertByteArrayToUInt(refineKey, i);
            }
            return formattedKey;
        }
        private static byte[] ConvertUIntToByteArray(uint v)
        {
            byte[] result = new byte[4];
            result[0] = (byte)((v >> 24) & 0xFF);
            result[1] = (byte)((v >> 16) & 0xFF);
            result[2] = (byte)((v >> 8) & 0xFF);
            result[3] = (byte)((v >> 0) & 0xFF);
            return result;
        }
        private static uint ConvertByteArrayToUInt(byte[] v, int offset)
        {
            if (offset + 4 > v.Length)
            {
                return 0;
            }
            uint output;
            output = (uint)(v[offset] << 24);
            output |= (uint)(v[offset + 1] << 16);
            output |= (uint)(v[offset + 2] << 8);
            output |= (uint)(v[offset + 3] << 0);
            return output;
        }
    }

作者: 薆要执著    时间: 2018-7-21 15:59
贴代码还是用代码标签贴吧
作者: a422880152    时间: 2018-7-22 10:07
已将很不错了




欢迎光临 精易论坛 (https://125.confly.eu.org/) Powered by Discuz! X3.4