Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ///
- /// WoLfulus.com
- ///
- using System;
- using System.IO;
- using System.Linq;
- namespace GameNetwork.Protocol
- {
- /// <summary>
- /// Modulus
- /// </summary>
- class Modulus
- {
- /// <summary>
- /// Constants
- /// </summary>
- const int KEYFILE_ALLKEY = 0x1111;
- const int KEYFILE_ONEKEY = 0x1112;
- const int ENCRYPTION_KEY_SIZE = 4;
- const int ENCRYPTION_BLOCK_SIZE = 8;
- const int ENCRYPTED_BLOCK_SIZE = 11;
- private static byte[] m_bXORKey = new byte[] {
- 0xE7, 0x6D, 0x3A, 0x89, 0xBC, 0xB2, 0x9F, 0x73, 0x23, 0xA8, 0xFE, 0xB6, 0x49, 0x5D, 0x39, 0x5D,
- 0x8A, 0xCB, 0x63, 0x8D, 0xEA, 0x7D, 0x2B, 0x5F, 0xC3, 0xB1, 0xE9, 0x83, 0x29, 0x51, 0xE8, 0x56
- };
- /// <summary>
- /// Variables
- /// </summary>
- private uint[] m_dwModulus = new uint[ENCRYPTION_KEY_SIZE] { 0, 0, 0, 0 };
- private uint[] m_dwEncryptionKey = new uint[ENCRYPTION_KEY_SIZE] { 0, 0, 0, 0 };
- private uint[] m_dwDecryptionKey = new uint[ENCRYPTION_KEY_SIZE] { 0, 0, 0, 0 };
- private uint[] m_dwXORKey = new uint[ENCRYPTION_KEY_SIZE] { 0, 0, 0, 0 };
- /// <summary>
- /// Embeded Keys
- /// </summary>
- ///
- public static uint[,] ClientEncryptionKeys = new uint[,] {
- { 23489, 11911, 19816, 13647 },
- { 128079, 164742, 70235, 106898 },
- { 48413, 46165, 15171, 37433 }
- };
- public static uint[,] ClientDecryptionKeys = new uint[,] {
- { 18035, 30340, 24701, 11141 },
- { 73326, 109989, 98843, 171058 },
- { 62004, 64409, 35374, 64599 }
- };
- public static uint[,] ServerDecryptionKeys = new uint[,] {
- { 31544, 2047, 57011, 10183 },
- { 128079, 164742, 70235, 106898 },
- { 48413, 46165, 15171, 37433 }
- };
- public static uint[,] ServerEncryptionKeys = new uint[,] {
- { 13169, 19036, 35482, 29587 },
- { 73326, 109989, 98843, 171058 },
- { 62004, 64409, 35374, 64599 }
- };
- /// <summary>
- /// Mask
- /// </summary>
- private static uint[] s_dwSaveLoadXOR = new uint[ENCRYPTION_KEY_SIZE] { 0x3F08A79B, 0xE25CC287, 0x93D27AB9, 0x20DEA7BF };
- /// <summary>
- /// Encryption
- /// </summary>
- public byte[] Encrypt(byte[] buffer)
- {
- int iTotalSize = ((buffer.Length + ENCRYPTION_BLOCK_SIZE - 1) / ENCRYPTION_BLOCK_SIZE) * ENCRYPTED_BLOCK_SIZE;
- using (MemoryStream encrypted = new MemoryStream(iTotalSize))
- {
- for (int i = 0; i < buffer.Length; i += ENCRYPTION_BLOCK_SIZE)
- {
- byte[] block = EncryptBlock(buffer.Skip(i).ToArray());
- encrypted.Write(block, 0, block.Length);
- }
- return encrypted.ToArray();
- }
- }
- private byte[] EncryptBlock(byte[] buffer)
- {
- int nSize = Math.Min(8, buffer.Length);
- uint[] dwEncBuffer = Enumerable.Repeat<uint>(0, ENCRYPTION_KEY_SIZE).ToArray();
- byte[] lpTarget = Enumerable.Repeat<byte>(0, ENCRYPTED_BLOCK_SIZE).ToArray();
- byte[] lpSource = new byte[ENCRYPTION_BLOCK_SIZE];
- Buffer.BlockCopy(buffer, 0, lpSource, 0, nSize);
- uint dwPrev = 0;
- int lpSrcOffset = 0;
- for (int i = 0; i < ENCRYPTION_KEY_SIZE; i++, lpSrcOffset += 2)
- {
- uint dwNext = BitConverter.ToUInt16(lpSource, lpSrcOffset);
- dwEncBuffer[i] = ((dwNext ^ m_dwXORKey[i] ^ dwPrev) * m_dwEncryptionKey[i]) % m_dwModulus[i];
- dwPrev = dwEncBuffer[i] & 0xFFFF;
- }
- dwPrev = dwEncBuffer[ENCRYPTION_KEY_SIZE - 1] & 0xFFFF;
- for (int i = 2; i >= 0; i--)
- {
- uint dwSrc = dwEncBuffer[i] & 0xFFFF;
- dwEncBuffer[i] = dwEncBuffer[i] ^ m_dwXORKey[i] ^ dwPrev;
- dwPrev = dwSrc;
- }
- int nTotalBits = 0;
- for (int i = 0; i < ENCRYPTION_KEY_SIZE; i++)
- {
- nTotalBits = AddBits(ref lpTarget, nTotalBits, KeysToBytes(dwEncBuffer, i), 0, 16);
- nTotalBits = AddBits(ref lpTarget, nTotalBits, KeysToBytes(dwEncBuffer, i), 22, 2);
- }
- byte[] cCheckSum = new byte[2] { (byte)((nSize & 0xFF) ^ 0x3D), 0xF8 };
- for (int i = 0; i < ENCRYPTION_BLOCK_SIZE; i++)
- {
- cCheckSum[1] ^= lpSource[i];
- }
- cCheckSum[0] ^= cCheckSum[1];
- nTotalBits = AddBits(ref lpTarget, nTotalBits, cCheckSum, 0, 16);
- return lpTarget;
- }
- /// <summary>
- /// Decryption
- /// </summary>
- public byte[] Decrypt(byte[] buffer)
- {
- int iTotalSize = ((buffer.Length + ENCRYPTED_BLOCK_SIZE - 1) / ENCRYPTED_BLOCK_SIZE) * ENCRYPTION_BLOCK_SIZE;
- using (MemoryStream decrypted = new MemoryStream(iTotalSize))
- {
- for (int i = 0; i < buffer.Length; i += ENCRYPTED_BLOCK_SIZE)
- {
- var encryptedBlock = buffer.Skip(i).ToArray();
- byte[] block = DecryptBlock(encryptedBlock);
- if (block.Length == 0)
- {
- return block; // Error
- }
- decrypted.Write(block, 0, block.Length);
- }
- return decrypted.ToArray();
- }
- }
- private byte[] DecryptBlock(byte[] buffer)
- {
- //int nSize = Math.Min(8, buffer.Length);
- uint[] dwDecBuffer = Enumerable.Repeat<uint>(0, ENCRYPTION_KEY_SIZE).ToArray();
- byte[] lpTarget = Enumerable.Repeat<byte>(0, ENCRYPTED_BLOCK_SIZE).ToArray();
- byte[] lpEncrypted = new byte[buffer.Length];
- Buffer.BlockCopy(buffer, 0, lpEncrypted, 0, buffer.Length);
- int nTotalBits = 0;
- for (int i = 0; i < ENCRYPTION_KEY_SIZE; i++)
- {
- byte[] tempBuffer = new byte[4];
- AddBits(ref tempBuffer, 0, lpEncrypted, nTotalBits, 16);
- nTotalBits += 16;
- AddBits(ref tempBuffer, 22, lpEncrypted, nTotalBits, 2);
- nTotalBits += 2;
- dwDecBuffer[i] = BitConverter.ToUInt32(tempBuffer, 0);
- }
- uint dwPrev = dwDecBuffer[ENCRYPTION_KEY_SIZE - 1] & 0xFFFF;
- for (int i = 2; i >= 0; i--)
- {
- dwDecBuffer[i] ^= m_dwXORKey[i];
- dwDecBuffer[i] ^= dwPrev;
- dwPrev = dwDecBuffer[i] & 0xFFFF;
- }
- dwPrev = 0;
- int offset = 0;
- for (int i = 0; i < ENCRYPTION_KEY_SIZE; i++, offset += 2)
- {
- uint dwResult = (dwDecBuffer[i] * m_dwDecryptionKey[i]) % m_dwModulus[i] ^ m_dwXORKey[i] ^ dwPrev;
- byte[] temp = BitConverter.GetBytes(dwResult);
- lpTarget[offset + 0] = temp[0];
- lpTarget[offset + 1] = temp[1];
- dwPrev = dwDecBuffer[i] & 0xFFFF;
- }
- byte[] cCheckSum = { 0, 0 };
- AddBits(ref cCheckSum, 0, lpEncrypted, nTotalBits, 16);
- nTotalBits += 16;
- cCheckSum[0] = (byte)((cCheckSum[1] ^ (cCheckSum[0] ^ 0x3D)) & 0xFF);
- byte cTempCheckSum = 0xF8;
- for (int i = 0; i < ENCRYPTION_BLOCK_SIZE; i++)
- {
- cTempCheckSum ^= lpTarget[i];
- }
- if (cCheckSum[1] != cTempCheckSum)
- {
- return new byte[0];
- }
- return lpTarget.Take(cCheckSum[0]).ToArray();
- }
- /// <summary>
- /// Helper functions
- /// </summary>
- public int GetByteOfBit(int nBit)
- {
- return nBit >> 3;
- }
- byte[] KeysToBytes(uint[] keys, int offset)
- {
- using (MemoryStream stream = new MemoryStream(keys.Length * sizeof(uint)))
- {
- for (int i = offset; i < keys.Length; i++)
- {
- var bytes = BitConverter.GetBytes(keys[i]);
- stream.Write(bytes, 0, bytes.Length);
- }
- return stream.ToArray();
- }
- }
- private int AddBits(ref byte[] lpBuffer, int nNumBufferBits, byte[] lpBits, int nInitialBit, int nNumBits)
- {
- int nBufferSize = (GetByteOfBit((nNumBits + nInitialBit) - 1) - GetByteOfBit(nInitialBit)) + 1;
- byte[] lpTemp = Enumerable.Repeat<byte>(0, nBufferSize + 1).ToArray();
- Buffer.BlockCopy(lpBits, GetByteOfBit(nInitialBit), lpTemp, 0, nBufferSize);
- int nLastBitMod8 = (nNumBits + nInitialBit) % ENCRYPTION_BLOCK_SIZE;
- if (nLastBitMod8 != 0)
- {
- lpTemp[nBufferSize - 1] &= (byte)(((nLastBitMod8 | 0xFF) << (ENCRYPTION_BLOCK_SIZE - nLastBitMod8)) & 0xFF);
- }
- int nShiftLeft = (nInitialBit % ENCRYPTION_BLOCK_SIZE);
- int nShiftRight = (nNumBufferBits % ENCRYPTION_BLOCK_SIZE);
- Shift(ref lpTemp, nBufferSize, -nShiftLeft);
- Shift(ref lpTemp, nBufferSize + 1, nShiftRight);
- int nMax = ((nShiftRight <= nShiftLeft) ? 0 : 1) + nBufferSize;
- int offset = GetByteOfBit(nNumBufferBits);
- for (int i = 0; i < nMax; i++)
- {
- lpBuffer[i + offset] |= lpTemp[i];
- }
- return nNumBufferBits + nNumBits;
- }
- void Shift(ref byte[] lpBuffer, int nByte, int nShift)
- {
- if (nShift == 0)
- {
- return;
- }
- if (nShift > 0)
- {
- int lpTemp = nByte - 1;
- for (int i = nByte - 1; i > 0; i--, lpTemp--)
- {
- lpBuffer[lpTemp] = (byte)(((lpBuffer[lpTemp - 1] << (ENCRYPTION_BLOCK_SIZE - nShift)) | (lpBuffer[lpTemp] >> nShift)) & 0xFF);
- }
- lpBuffer[lpTemp] = (byte)((lpBuffer[lpTemp] >> nShift) & 0xFF);
- }
- else
- {
- int nRealShift = -nShift;
- int lpTemp = 0;
- for (int i = 0; i < nByte - 1; i++, lpTemp++)
- {
- lpBuffer[lpTemp] = (byte)(((lpBuffer[lpTemp + 1] >> (ENCRYPTION_BLOCK_SIZE - nRealShift)) | (lpBuffer[lpTemp] << nRealShift)) & 0xFF);
- }
- lpBuffer[lpTemp] = (byte)((lpBuffer[lpTemp] << nRealShift) & 0xFF);
- }
- }
- /// <summary>
- /// Keys
- /// </summary>
- private int GetKeyFileSize(int x)
- {
- return (((x) * (sizeof(uint) * ENCRYPTION_KEY_SIZE)) + sizeof(uint) + sizeof(ushort));
- }
- private bool LoadKey(string lpszFileName, ushort wFileHeader, bool bLoadModulus, bool bLoadEncKey, bool bLoadDecKey, bool bLoadXORKey)
- {
- //uint[] dwBuffer = new uint[ENCRYPTION_KEY_SIZE];
- if (!File.Exists(lpszFileName))
- {
- throw new FileNotFoundException("File doesn't exists.");
- }
- var buffer = File.ReadAllBytes(lpszFileName);
- var headerType = BitConverter.ToUInt16(buffer, 0);
- var headerSize = BitConverter.ToUInt32(buffer, 2);
- //
- // Make sure the Header it's fine.
- //
- int keyFileSize = GetKeyFileSize(
- Convert.ToInt32(bLoadModulus) +
- Convert.ToInt32(bLoadEncKey) +
- Convert.ToInt32(bLoadDecKey) +
- Convert.ToInt32(bLoadXORKey)
- );
- if (headerType != wFileHeader || headerSize != keyFileSize)
- {
- throw new Exception("Key file header mismatch.");
- }
- int offset = 6;
- if (bLoadModulus)
- {
- for (int i = 0; i < ENCRYPTION_KEY_SIZE; i++)
- {
- m_dwModulus[i] = s_dwSaveLoadXOR[i] ^ BitConverter.ToUInt32(buffer, offset);
- offset += sizeof(uint);
- }
- }
- if (bLoadEncKey)
- {
- for (int i = 0; i < ENCRYPTION_KEY_SIZE; i++)
- {
- m_dwEncryptionKey[i] = s_dwSaveLoadXOR[i] ^ BitConverter.ToUInt32(buffer, offset);
- offset += sizeof(uint);
- }
- }
- if (bLoadDecKey)
- {
- for (int i = 0; i < ENCRYPTION_KEY_SIZE; i++)
- {
- m_dwDecryptionKey[i] = s_dwSaveLoadXOR[i] ^ BitConverter.ToUInt32(buffer, offset);
- offset += sizeof(uint);
- }
- }
- if (bLoadXORKey)
- {
- for (int i = 0; i < ENCRYPTION_KEY_SIZE; i++)
- {
- m_dwXORKey[i] = s_dwSaveLoadXOR[i] ^ BitConverter.ToUInt32(buffer, offset);
- offset += sizeof(uint);
- }
- }
- return true;
- }
- /// <summary>
- /// Key setters
- /// </summary>
- public bool SetEncryptionKey(uint[,] keys)
- {
- this.m_dwEncryptionKey[0] = keys[0, 0];
- this.m_dwEncryptionKey[1] = keys[0, 1];
- this.m_dwEncryptionKey[2] = keys[0, 2];
- this.m_dwEncryptionKey[3] = keys[0, 3];
- this.m_dwDecryptionKey[0] = 0;
- this.m_dwDecryptionKey[1] = 0;
- this.m_dwDecryptionKey[2] = 0;
- this.m_dwDecryptionKey[3] = 0;
- this.m_dwModulus[0] = keys[1, 0];
- this.m_dwModulus[1] = keys[1, 1];
- this.m_dwModulus[2] = keys[1, 2];
- this.m_dwModulus[3] = keys[1, 3];
- this.m_dwXORKey[0] = keys[2, 0];
- this.m_dwXORKey[1] = keys[2, 1];
- this.m_dwXORKey[2] = keys[2, 2];
- this.m_dwXORKey[3] = keys[2, 3];
- return true;
- }
- public bool SetDecryptionKey(uint[,] keys)
- {
- this.m_dwEncryptionKey[0] = 0;
- this.m_dwEncryptionKey[1] = 0;
- this.m_dwEncryptionKey[2] = 0;
- this.m_dwEncryptionKey[3] = 0;
- this.m_dwDecryptionKey[0] = keys[0, 0];
- this.m_dwDecryptionKey[1] = keys[0, 1];
- this.m_dwDecryptionKey[2] = keys[0, 2];
- this.m_dwDecryptionKey[3] = keys[0, 3];
- this.m_dwModulus[0] = keys[1, 0];
- this.m_dwModulus[1] = keys[1, 1];
- this.m_dwModulus[2] = keys[1, 2];
- this.m_dwModulus[3] = keys[1, 3];
- this.m_dwXORKey[0] = keys[2, 0];
- this.m_dwXORKey[1] = keys[2, 1];
- this.m_dwXORKey[2] = keys[2, 2];
- this.m_dwXORKey[3] = keys[2, 3];
- return true;
- }
- /// <summary>
- /// Key loaders
- /// </summary>
- public bool LoadEncryptionKey(string path)
- {
- return LoadKey(path, KEYFILE_ONEKEY, true, true, false, true);
- }
- public bool LoadDecryptionKey(string path)
- {
- return LoadKey(path, KEYFILE_ONEKEY, true, false, true, true);
- }
- ///
- /// Simple
- ///
- public static void XorEncode(ref byte[] buffer, int headerSize)
- {
- XorData(ref buffer, headerSize + 1, buffer.Length, 1);
- }
- public static void XorDecode(ref byte[] buffer, int headerSize)
- {
- XorData(ref buffer, buffer.Length - 1, headerSize, -1);
- }
- private static void XorData(ref byte[] buffer, int start, int end, int dir)
- {
- for (int i = start; i != end; i += dir)
- {
- buffer[i] ^= (byte)(buffer[i - 1] ^ m_bXORKey[i % m_bXORKey.Length]);
- }
- }
- public static void XorEncodeInline(ref byte[] buffer, int headerSize)
- {
- var start = 1;
- var length = buffer.Length - 1;
- var pos = start;
- for (int i = start; i < start + length; i++)
- {
- buffer[pos] ^= (byte)(m_bXORKey[(pos + headerSize) % m_bXORKey.Length] ^ buffer[pos - 1]);
- pos++;
- }
- }
- public static void XorDecodeInline(ref byte[] buffer)
- {
- var k = buffer.Length;
- for (int i = buffer.Length - 1; i >= 1; i--)
- {
- buffer[i] ^= (byte)(m_bXORKey[k % m_bXORKey.Length] ^ buffer[i - 1]);
- k--;
- }
- }
- public static void Mask(ref byte[] buffer, int offset, int length)
- {
- int k = 0;
- byte[] mask = new byte[] { 0xFC, 0xCF, 0xAB };
- for (int i = offset; i < length; i++)
- {
- buffer[i] = (byte)(buffer[i] ^ mask[k++ % mask.Length]);
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement