using System; namespace SogClient { internal sealed class PackUtils { internal static uint BE_To_UInt32(byte[] bs, int off) { return (uint)bs[off] << 24 | (uint)bs[off + 1] << 16 | (uint)bs[off + 2] << 8 | (uint)bs[off + 3]; } internal static void UInt32_To_BE(uint n, byte[] bs, int off) { bs[off] = (byte)(n >> 24); bs[off + 1] = (byte)(n >> 16); bs[off + 2] = (byte)(n >> 8); bs[off + 3] = (byte)(n); } } public class SogFastXTEAKey { private const int delta = unchecked((int)0x9E3779B9); private uint[] _S = new uint[4]; public byte[] Key { get; } public uint[] Sum0 { get; } public uint[] Sum1 { get; } public SogFastXTEAKey(byte[] srcKey) { if(srcKey.Length != 16) { TraceLog.Error("SogFastXTEAKey key length must is error {0}", srcKey); throw new Exception("SogXTEAKey key length must is 16"); } Key = srcKey; Sum0 = new uint[SogFastXTEA.Rounds]; Sum1 = new uint[SogFastXTEA.Rounds]; int i, j; for (i = j = 0; i < 4; i++, j += 4) { _S[i] = PackUtils.BE_To_UInt32(srcKey, j); } for (i = j = 0; i < SogFastXTEA.Rounds; i++) { Sum0[i] = ((uint)j + _S[j & 3]); j += delta; Sum1[i] = ((uint)j + _S[j >> 11 & 3]); } } } /// /// XTEA加密的变种,小于8个字节不加密,轮数量减少到8,提高效率 /// public sealed class SogFastXTEA { public const int Rounds = 8; private const int delta = unchecked((int)0x9E3779B9); private SogFastXTEA() { } public static void Encrypt(byte[] data, SogFastXTEAKey key) { int iBlockCount = data.Length / 8; int offset = 0; for(int block = 0; block < iBlockCount; block++) { uint v0 = PackUtils.BE_To_UInt32(data, offset); uint v1 = PackUtils.BE_To_UInt32(data, offset + 4); for (int i = 0; i < Rounds; i++) { v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ key.Sum0[i]; v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ key.Sum1[i]; } PackUtils.UInt32_To_BE(v0, data, offset); PackUtils.UInt32_To_BE(v1, data, offset + 4); offset += 8; } } public static void Decrypt(byte[] data, SogFastXTEAKey key) { int iBlockCount = data.Length / 8; int offset = 0; for (int block = 0; block < iBlockCount; block++) { uint v0 = PackUtils.BE_To_UInt32(data, offset); uint v1 = PackUtils.BE_To_UInt32(data, offset + 4); for (int i = Rounds - 1; i >= 0; i--) { v1 -= ((v0 << 4 ^ v0 >> 5) + v0) ^ key.Sum1[i]; v0 -= ((v1 << 4 ^ v1 >> 5) + v1) ^ key.Sum0[i]; } PackUtils.UInt32_To_BE(v0, data, offset); PackUtils.UInt32_To_BE(v1, data, offset + 4); offset += 8; } } } }