), here a reworked RC5 cipher for the password encryption. It uses pointers, so it can be considered as unsafe. It will work on any client, but newer client will need to generate a BufKey with the seed while older client only need the specified BufKey posted in the code. Newer clients also need another cipher, but the RC5 is still used.PS. This should generate a valid BufKey for the specified seed. (5180+) I can't test it, but it reproduce the rand(), srand() function.
Code:
public Byte[] Generate(Int32 Seed)
{
Byte[] BufKey = new Byte[0x10];
for (SByte i = 0; i < BufKey.Length; i++)
{
Seed *= 0x0343FD;
Seed += 0x269EC3;
BufKey[i] = (Byte)((Int16)((Seed >> 0x10) & 0x7FFF));
}
return BufKey;
}
Code:
// * ************************************************************
// * * START: corc5.cs *
// * ************************************************************
// * ************************************************************
// * INFORMATIONS
// * ************************************************************
// * Conquer Online RC5 for the library.
// * corc5.cs
// *
// * --
// *
// * Feel free to use this class in your projects, but don't
// * remove the header to keep the paternity of the class.
// *
// * ************************************************************
// * CREDITS
// * ************************************************************
// * Originally created by CptSky (May 10th, 2011)
// * Copyright (C) 2011 CptSky
// *
// * ************************************************************
// * CHANGE LOG
// * ************************************************************
// *
// * ************************************************************
using System;
using System.Runtime.InteropServices;
namespace CO2_CORE_DLL.Security
{
/// <summary>
/// Conquer Online Rivest Cipher 5
/// </summary>
public unsafe class CORC5
{
protected const Int32 RC5_32 = 32;
protected const Int32 RC5_12 = 12;
protected const Int32 RC5_SUB = (RC5_12 * 2 + 2);
protected const Int32 RC5_16 = 16;
protected const Int32 RC5_KEY = (RC5_16 / 4);
protected UInt32* m_BufKey = null;
protected UInt32* m_BufSub = null;
protected UInt32 RC5_PW32 = 0xB7E15163;
protected UInt32 RC5_QW32 = 0x9E3779B9;
/// <summary>
/// Create a new RC5 instance.
/// </summary>
public CORC5() { }
/// <summary>
/// Create a new RC5 instance with the specified magics numbers. (Shouldn't be used)
/// </summary>
public CORC5(UInt32 RC5_PW32, UInt32 RC5_QW32)
{
this.RC5_PW32 = RC5_PW32;
this.RC5_QW32 = RC5_QW32;
}
~CORC5()
{
if (m_BufKey != null)
Marshal.FreeHGlobal((IntPtr)m_BufKey);
if (m_BufSub != null)
Marshal.FreeHGlobal((IntPtr)m_BufSub);
}
/// <summary>
/// Generates a random key (Key) to use for the algorithm.
/// CO2: { 0x3C, 0xDC, 0xFE, 0xE8, 0xC4, 0x54, 0xD6, 0x7E, 0x16, 0xA6, 0xF8, 0x1A, 0xE8, 0xD0, 0x38, 0xBE }
/// </summary>
public void GenerateKey(Byte* pBufKey, Int32 Length)
{
if (pBufKey == null)
throw new NullReferenceException("Buffer can't be null!");
if (Length != RC5_16)
throw new Exception("Buffer length should be " + RC5_16 + "!");
if (m_BufKey != null)
Marshal.FreeHGlobal((IntPtr)m_BufKey);
if (m_BufSub != null)
Marshal.FreeHGlobal((IntPtr)m_BufSub);
m_BufKey = (UInt32*)Marshal.AllocHGlobal(RC5_KEY * sizeof(UInt32));
m_BufSub = (UInt32*)Marshal.AllocHGlobal(RC5_SUB * sizeof(UInt32));
for (Int32 z = 0; z < RC5_KEY; z++)
m_BufKey[z] = ((UInt32*)pBufKey)[z];
m_BufSub[0] = RC5_PW32;
Int32 i, j, k;
for (i = 1; i < RC5_SUB; i++)
m_BufSub[i] = m_BufSub[i - 1] - RC5_QW32;
UInt32 x, y;
i = j = 0;
x = y = 0;
for (k = 0; k < 3 * Math.Max(RC5_KEY, RC5_SUB); k++)
{
m_BufSub[i] = rotl((m_BufSub[i] + x + y), 3);
x = m_BufSub[i];
i = (i + 1) % RC5_SUB;
m_BufKey[j] = rotl((m_BufKey[j] + x + y), (x + y));
y = m_BufKey[j];
j = (j + 1) % RC5_KEY;
}
}
/// <summary>
/// Generates a random key (Key) to use for the algorithm.
/// CO2: { 0x3C, 0xDC, 0xFE, 0xE8, 0xC4, 0x54, 0xD6, 0x7E, 0x16, 0xA6, 0xF8, 0x1A, 0xE8, 0xD0, 0x38, 0xBE }
/// </summary>
public void GenerateKey(Byte[] BufKey)
{
if (BufKey == null)
throw new NullReferenceException("Buffer can't be null!");
if (BufKey.Length != RC5_16)
throw new Exception("Buffer length should be " + RC5_16 + "!");
if (m_BufKey != null)
Marshal.FreeHGlobal((IntPtr)m_BufKey);
if (m_BufSub != null)
Marshal.FreeHGlobal((IntPtr)m_BufSub);
m_BufKey = (UInt32*)Marshal.AllocHGlobal(RC5_KEY * sizeof(UInt32));
m_BufSub = (UInt32*)Marshal.AllocHGlobal(RC5_SUB * sizeof(UInt32));
fixed (Byte* pBufKey = BufKey)
{
for (Int32 z = 0; z < RC5_KEY; z++)
m_BufKey[z] = ((UInt32*)pBufKey)[z];
}
m_BufSub[0] = RC5_PW32;
Int32 i, j, k;
for (i = 1; i < RC5_SUB; i++)
m_BufSub[i] = m_BufSub[i - 1] - RC5_QW32;
UInt32 x, y;
i = j = 0;
x = y = 0;
for (k = 0; k < 3 * Math.Max(RC5_KEY, RC5_SUB); k++)
{
m_BufSub[i] = rotl((m_BufSub[i] + x + y), 3);
x = m_BufSub[i];
i = (i + 1) % RC5_SUB;
m_BufKey[j] = rotl((m_BufKey[j] + x + y), (x + y));
y = m_BufKey[j];
j = (j + 1) % RC5_KEY;
}
}
/// <summary>
/// Encrypts data with the CORC5 algorithm.
/// </summary>
public void Encrypt(Byte* pBuf, Int32 Length)
{
if (Length % 8 != 0)
throw new Exception("Buffer length should be a multiple of 8.");
Length = (Length / 8) * 8;
if (Length <= 0)
throw new Exception("Buffer length should be greater than 0.");
if (pBuf == null)
throw new NullReferenceException("Buffer can't be null!");
UInt32* pBufData = (UInt32*)pBuf;
for (Int32 k = 0; k < Length / 8; k++)
{
UInt32 a = pBufData[2 * k];
UInt32 b = pBufData[2 * k + 1];
UInt32 le = a + m_BufSub[0];
UInt32 re = b + m_BufSub[1];
for (Int32 i = 1; i <= RC5_12; i++)
{
le = rotl((le ^ re), re) + m_BufSub[2 * i];
re = rotl((re ^ le), le) + m_BufSub[2 * i + 1];
}
pBufData[2 * k] = le;
pBufData[2 * k + 1] = re;
}
}
/// <summary>
/// Encrypts data with the CORC5 algorithm.
/// </summary>
public void Encrypt(ref Byte[] Buf)
{
if (Buf == null)
throw new NullReferenceException("Buffer can't be null!");
Int32 Length = Buf.Length;
if (Length % 8 != 0)
throw new Exception("Buffer length should be a multiple of 8.");
Length = (Length / 8) * 8;
if (Length <= 0)
throw new Exception("Buffer length should be greater than 0.");
UInt32* pBufData = null;
fixed (Byte* pBuf = Buf)
pBufData = (UInt32*)pBuf;
for (Int32 k = 0; k < Length / 8; k++)
{
UInt32 a = pBufData[2 * k];
UInt32 b = pBufData[2 * k + 1];
UInt32 le = a + m_BufSub[0];
UInt32 re = b + m_BufSub[1];
for (Int32 i = 1; i <= RC5_12; i++)
{
le = rotl((le ^ re), re) + m_BufSub[2 * i];
re = rotl((re ^ le), le) + m_BufSub[2 * i + 1];
}
pBufData[2 * k] = le;
pBufData[2 * k + 1] = re;
}
}
/// <summary>
/// Decrypts data with the CORC5 algorithm.
/// </summary>
public void Decrypt(Byte* pBuf, Int32 Length)
{
if (Length % 8 != 0)
throw new Exception("Buffer length should be a multiple of 8.");
Length = (Length / 8) * 8;
if (Length <= 0)
throw new Exception("Buffer length should be greater than 0.");
if (pBuf == null)
throw new NullReferenceException("Buffer can't be null!");
UInt32* pBufData = (UInt32*)pBuf;
for (Int32 k = 0; k < Length / 8; k++)
{
UInt32 ld = pBufData[2 * k];
UInt32 rd = pBufData[2 * k + 1];
for (Int32 i = RC5_12; i >= 1; i--)
{
rd = rotr((rd - m_BufSub[2 * i + 1]), ld) ^ ld;
ld = rotr((ld - m_BufSub[2 * i]), rd) ^ rd;
}
UInt32 b = rd - m_BufSub[1];
UInt32 a = ld - m_BufSub[0];
pBufData[2 * k] = a;
pBufData[2 * k + 1] = b;
}
}
/// <summary>
/// Decrypts data with the CORC5 algorithm.
/// </summary>
public void Decrypt(ref Byte[] Buf)
{
if (Buf == null)
throw new NullReferenceException("Buffer can't be null!");
Int32 Length = Buf.Length;
if (Length % 8 != 0)
throw new Exception("Buffer length should be a multiple of 8.");
Length = (Length / 8) * 8;
if (Length <= 0)
throw new Exception("Buffer length should be greater than 0.");
UInt32* pBufData = null;
fixed (Byte* pBuf = Buf)
pBufData = (UInt32*)pBuf;
for (Int32 k = 0; k < Length / 8; k++)
{
UInt32 ld = pBufData[2 * k];
UInt32 rd = pBufData[2 * k + 1];
for (Int32 i = RC5_12; i >= 1; i--)
{
rd = rotr((rd - m_BufSub[2 * i + 1]), ld) ^ ld;
ld = rotr((ld - m_BufSub[2 * i]), rd) ^ rd;
}
UInt32 b = rd - m_BufSub[1];
UInt32 a = ld - m_BufSub[0];
pBufData[2 * k] = a;
pBufData[2 * k + 1] = b;
}
}
protected UInt32 rotl(UInt32 Value, UInt32 Count)
{
Count %= 32;
UInt32 High = Value >> (32 - (Int32)Count);
return (Value << (Int32)Count) | High;
}
protected UInt32 rotr(UInt32 Value, UInt32 Count)
{
Count %= 32;
UInt32 Low = Value << (32 - (Int32)Count);
return (Value >> (Int32)Count) | Low;
}
}
}
// * ************************************************************
// * * END: corc5.cs *
// * ************************************************************






