195 lines
4.2 KiB
C#
195 lines
4.2 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
|
|
// ReSharper disable once CheckNamespace
|
|
namespace VMProtect
|
|
{
|
|
public class CipherRC5
|
|
{
|
|
private const int R = 15; // number of rounds
|
|
private const int B = 8; // number of bytes in key
|
|
private const int C = 8 * B / BitRotate.W; // 16 - number u32s in key = ceil(8*B/W)
|
|
private const int T = 2 * (R + 1); // 34 - size of table _s = 2*(R+1) u32s
|
|
|
|
private readonly uint[] _s; // expanded key table
|
|
|
|
#if RUNTIME
|
|
private const uint P = (uint)Faces.RC5_P;
|
|
private const uint Q = (uint)Faces.RC5_Q;
|
|
#else
|
|
private static readonly uint P = Core.Instance.Rand32();
|
|
private static readonly uint Q = Core.Instance.Rand32();
|
|
|
|
public static byte[] CreateRandomKey()
|
|
{
|
|
var ret = new byte[B];
|
|
Core.Instance.RndGenerator.NextBytes(ret);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
public CipherRC5(byte[] key)
|
|
{
|
|
uint i, j, k, u = BitRotate.W / 8, a, b;
|
|
var l = new uint[C];
|
|
_s = new uint[T];
|
|
|
|
for (i = B - 1, l[C - 1] = 0; i != uint.MaxValue; i--)
|
|
l[i / u] = (l[i / u] << 8) + key[i];
|
|
|
|
for (_s[0] = P, i = 1; i < T; i++)
|
|
_s[i] = _s[i - 1] + Q;
|
|
for (a = b = i = j = k = 0; k < 3 * T; k++, i = (i + 1) % T, j = (j + 1) % C) // 3*T > 3*C
|
|
{
|
|
a = _s[i] = BitRotate.Left(_s[i] + a + b, 3);
|
|
b = l[j] = BitRotate.Left(l[j] + a + b, (int)(a + b));
|
|
}
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
private struct Dword
|
|
{
|
|
[FieldOffset(0)]
|
|
public ulong dw;
|
|
|
|
[FieldOffset(0)]
|
|
public uint w0;
|
|
|
|
[FieldOffset(4)]
|
|
public uint w1;
|
|
}
|
|
|
|
private void Encrypt(ref Dword io)
|
|
{
|
|
uint i, a = io.w0 + _s[0], b = io.w1 + _s[1];
|
|
for (i = 1; i <= R; i++)
|
|
{
|
|
a = BitRotate.Left(a ^ b, (int)b) + _s[2 * i];
|
|
b = BitRotate.Left(b ^ a, (int)a) + _s[2 * i + 1];
|
|
}
|
|
io.w0 = a;
|
|
io.w1 = b;
|
|
}
|
|
|
|
private void Decrypt(ref Dword io)
|
|
{
|
|
uint i, b = io.w1, a = io.w0;
|
|
for (i = R; i > 0; i--)
|
|
{
|
|
b = BitRotate.Right(b - _s[2 * i + 1], (int)a) ^ a;
|
|
a = BitRotate.Right(a - _s[2 * i], (int)b) ^ b;
|
|
}
|
|
io.w1 = b - _s[1];
|
|
io.w0 = a - _s[0];
|
|
}
|
|
|
|
public byte[] Encrypt(byte[] ain)
|
|
{
|
|
var aout = new byte[ain.Length];
|
|
Encrypt(ain, aout);
|
|
return aout;
|
|
}
|
|
|
|
public byte[] Decrypt(byte[] ain)
|
|
{
|
|
var aout = new byte[ain.Length];
|
|
Decrypt(ain, aout);
|
|
return aout;
|
|
}
|
|
|
|
public void Encrypt(byte[] ain, byte[] aout)
|
|
{
|
|
var block = new Dword();
|
|
for (var i = 0; i < ain.Length; i += 8)
|
|
{
|
|
block.dw = BitConverter.ToUInt64(ain, i);
|
|
Encrypt(ref block);
|
|
BitConverter.GetBytes(block.dw).CopyTo(aout, i);
|
|
}
|
|
}
|
|
|
|
public void Decrypt(byte[] ain, byte[] aout)
|
|
{
|
|
var block = new Dword();
|
|
for (var i = 0; i < ain.Length; i += 8)
|
|
{
|
|
block.dw = BitConverter.ToUInt64(ain, i);
|
|
Decrypt(ref block);
|
|
BitConverter.GetBytes(block.dw).CopyTo(aout, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class CRC32
|
|
{
|
|
static uint[] _table;
|
|
|
|
public CRC32()
|
|
{
|
|
if (_table == null)
|
|
{
|
|
_table = new uint[256];
|
|
for (var i = 0; i < 256; i++)
|
|
{
|
|
var entry = (uint)i;
|
|
for (var j = 0; j < 8; j++)
|
|
if ((entry & 1) == 1)
|
|
entry = (entry >> 1) ^ 0xedb88320u;
|
|
else
|
|
entry = entry >> 1;
|
|
_table[i] = entry;
|
|
}
|
|
}
|
|
}
|
|
|
|
public uint Hash(IntPtr ptr, uint size)
|
|
{
|
|
uint crc = 0;
|
|
for (var i = 0; i < size; i++)
|
|
crc = _table[(Marshal.ReadByte(new IntPtr(ptr.ToInt64() + i)) ^ crc) & 0xff] ^ (crc >> 8);
|
|
return ~crc;
|
|
}
|
|
}
|
|
|
|
public class CRCValueCryptor
|
|
{
|
|
private uint _key;
|
|
public CRCValueCryptor()
|
|
{
|
|
_key = (uint)Faces.CRC_INFO_SALT;
|
|
}
|
|
|
|
public uint Decrypt(uint value)
|
|
{
|
|
uint res = value ^ _key;
|
|
_key = BitRotate.Left(_key, 7) ^ res;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
public class BitRotate
|
|
{
|
|
public const int W = 32; // u32 size in bits
|
|
public static uint Left(uint a, int offset)
|
|
{
|
|
var r1 = a << offset;
|
|
var r2 = a >> (W - offset);
|
|
return r1 | r2;
|
|
}
|
|
|
|
public static uint Right(uint a, int offset)
|
|
{
|
|
var r1 = a >> offset;
|
|
var r2 = a << (W - offset);
|
|
return r1 | r2;
|
|
}
|
|
|
|
public static uint Swap(uint value)
|
|
{
|
|
uint mask_xx_zz = (value & 0x00FF00FFU);
|
|
uint mask_ww_yy = (value & 0xFF00FF00U);
|
|
return ((mask_xx_zz >> 8) | (mask_xx_zz << 24)) +
|
|
((mask_ww_yy << 8) | (mask_ww_yy >> 24));
|
|
}
|
|
}
|
|
} |