csharp/499116344/qqProtocol/QQ.Framework/Utils/QQTea.cs

QQTea.cs
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace QQ.Framework.Utils
{
    public static clast QQTea
    {
        private static void Code(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos, byte[] key)
        {
            if (outPos > 0)
            {
                for (var i = 0; i < 8; i++)
                {
                    In[outOffset + outPos + i] =
                        BitConverter.GetBytes(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i - 8])[0];
                }
            }

            var array = FormatKey(key);
            var num = ConvertByteArrayToUInt(In, outOffset + outPos);
            var num2 = ConvertByteArrayToUInt(In, outOffset + outPos + 4);
            var num3 = 0u;
            var num4 = 2654435769u;
            var num5 = 16u;
            while (num5-- > 0u)
            {
                num3 += num4;
                num += ((num2 > 5) + array[1]);
                num2 += ((num > 5) + array[3]);
            }

            Array.Copy(ConvertUIntToByteArray(num), 0, Out, outOffset + outPos, 4);
            Array.Copy(ConvertUIntToByteArray(num2), 0, Out, outOffset + outPos + 4, 4);
            if (inPos > 0)
            {
                for (var j = 0; j < 8; j++)
                {
                    Out[outOffset + outPos + j] =
                        BitConverter.GetBytes(Out[outOffset + outPos + j] ^ In[inOffset + inPos + j - 8])[0];
                }
            }
        }

        private static void Decode(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos,
            byte[] key)
        {
            if (outPos > 0)
            {
                for (var i = 0; i < 8; i++)
                {
                    Out[outOffset + outPos + i] =
                        BitConverter.GetBytes(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i - 8])[0];
                }
            }
            else
            {
                Array.Copy(In, inOffset, Out, outOffset, 8);
            }

            var array = FormatKey(key);
            var num = ConvertByteArrayToUInt(Out, outOffset + outPos);
            var num2 = ConvertByteArrayToUInt(Out, outOffset + outPos + 4);
            var num3 = 3816266640u;
            var num4 = 2654435769u;
            var num5 = 16u;
            while (num5-- > 0u)
            {
                num2 -= ((num > 5) + array[3]);
                num -= ((num2 > 5) + array[1]);
                num3 -= num4;
            }

            Array.Copy(ConvertUIntToByteArray(num), 0, Out, outOffset + outPos, 4);
            Array.Copy(ConvertUIntToByteArray(num2), 0, Out, outOffset + outPos + 4, 4);
        }

        public static byte[] Decrypt(byte[] In, byte[] key)
        {
            var into = new List();
            var tail = true;
            for (var i = In.Length - 1; i >= 0; i--)
            {
                if (tail)
                {
                    if (In[i] == 0x03)
                    {
                        tail = false;
                    }
                    else if (In[i] == 0x00)
                    {
                    }
                    else
                    {
                        into.Insert(0, In[i]);
                        tail = false;
                    }
                }
                else
                {
                    into.Insert(0, In[i]);
                }
            }

            return Decrypt(into.ToArray(), 0, into.Count, key);
        }

        public static byte[] Decrypt(byte[] In, int offset, int len, byte[] key)
        {
            var temp = new byte[In.Length];
            Buffer.BlockCopy(In, 0, temp, 0, In.Length);
            if (len % 8 != 0 || len < 16)
            {
                return null;
            }

            var array = new byte[len];
            for (var i = 0; i < len; i += 8)
            {
                Decode(temp, offset, i, array, 0, i, key);
            }

            for (var j = 8; j < len; j++)
            {
                array[j] ^= temp[offset + j - 8];
            }

            var num = array[0] & 7;
            len = len - num - 10;
            var array2 = new byte[len];
            Array.Copy(array, num + 3, array2, 0, len);
            return array2;
        }

        public static byte[] Encrypt(byte[] In, byte[] key)
        {
            return Encrypt(In, 0, In.Length, key);
        }

        public static byte[] Encrypt(byte[] In, int offset, int len, byte[] key)
        {
            var temp = new byte[In.Length];
            Buffer.BlockCopy(In, 0, temp, 0, In.Length);
            var random = new Random();
            var num = (len + 10) % 8;
            if (num != 0)
            {
                num = 8 - num;
            }

            var array = new byte[len + num + 10];
            array[0] = (byte) ((random.Next() & 248) | num);
            for (var i = 1; i < num + 3; i++)
            {
                array[i] = (byte) (random.Next() & 255);
            }

            Array.Copy(temp, 0, array, num + 3, len);
            for (var j = num + 3 + len; j < array.Length; j++)
            {
                array[j] = 0;
            }

            var array2 = new byte[len + num + 10];
            for (var k = 0; k < array2.Length; k += 8)
            {
                Code(array, 0, k, array2, 0, k, key);
            }

            return array2;
        }

        private static uint[] FormatKey(byte[] key)
        {
            if (key.Length == 0)
            {
                throw new ArgumentException("Key must be between 1 and 16 characters in length");
            }

            var array = new byte[16];
            if (key.Length < 16)
            {
                Array.Copy(key, 0, array, 0, key.Length);
                for (var i = key.Length; i < 16; i++)
                {
                    array[i] = 32;
                }
            }
            else
            {
                Array.Copy(key, 0, array, 0, 16);
            }

            var array2 = new uint[4];
            var num = 0;
            for (var j = 0; j < array.Length; j += 4)
            {
                array2[num++] = ConvertByteArrayToUInt(array, j);
            }

            return array2;
        }

        private static byte[] ConvertUIntToByteArray(uint v)
        {
            return new[]
            {
                (byte) ((v >> 24) & 255u),
                (byte) ((v >> 16) & 255u),
                (byte) ((v >> 8) & 255u),
                (byte) (v & 255u)
            };
        }

        private static uint ConvertByteArrayToUInt(byte[] v, int offset)
        {
            if (offset + 4 > v.Length)
            {
                return 0u;
            }

            var num = (uint) v[offset]