), this one use pointers, so it can be considered as unsafe. In general, the speed is better with this crypto, but it doesn't change a lot... (Few ms...) Anyway, I think that the code is better than my older cipher. Maybe it will interest some people.Special thanks to Sparkie for the IV generation algorithm.
Auth: Any client...
Game: 5017 & before...
Code:
// * ************************************************************
// * * START: cosac.cs *
// * ************************************************************
// * ************************************************************
// * INFORMATIONS
// * ************************************************************
// * Conquer Online Server Asymmetric Cipher for the library.
// * cosac.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
// *
// * ************************************************************
// * SPECIAL THANKS
// * ************************************************************
// * Sparkie (unknownone @ e*pvp)
// *
// * ************************************************************
// * CHANGE LOG
// * ************************************************************
// *
// * ************************************************************
using System;
namespace CO2_CORE_DLL.Security
{
/// <summary>
/// Conquer Online Server Asymmetric Cipher
/// </summary>
public unsafe class COSAC
{
protected const Int32 COSAC_IV = 512;
protected const Int32 COSAC_KEY = 512;
protected Byte* m_BufIV = null;
protected Byte* m_BufKey = null;
protected UInt16 EncryptCounter = 0;
protected UInt16 DecryptCounter = 0;
/// <summary>
/// Create a new COSAC instance.
/// </summary>
public COSAC() { }
~COSAC()
{
if (m_BufIV != null)
Marshal.FreeHGlobal((IntPtr)m_BufIV);
if (m_BufKey != null)
Marshal.FreeHGlobal((IntPtr)m_BufKey);
}
/// <summary>
/// Generates an initialization vector (IV) to use for the algorithm.
/// CO2(P: 0x13FA0F9D, G: 0x6D5C7962)
/// </summary>
public void GenerateIV(Int32 P, Int32 G)
{
if (m_BufIV != null)
Marshal.FreeHGlobal((IntPtr)m_BufIV);
m_BufIV = (Byte*)Marshal.AllocHGlobal(COSAC_IV);
Int16 K = COSAC_IV / 2;
Byte* pBufPKey = (Byte*)&P;
Byte* pBufGKey = (Byte*)&G;
for (Int16 i = 0; i < K; i++)
{
m_BufIV[i + 0] = pBufPKey[0];
m_BufIV[i + K] = pBufGKey[0];
pBufPKey[0] = (Byte)((pBufPKey[1] + (Byte)(pBufPKey[0] * pBufPKey[2])) * pBufPKey[0] + pBufPKey[3]);
pBufGKey[0] = (Byte)((pBufGKey[1] - (Byte)(pBufGKey[0] * pBufGKey[2])) * pBufGKey[0] + pBufGKey[3]);
}
}
/// <summary>
/// Generates a key (Key) to use for the algorithm and reset the encrypt counter.
/// In Conquer Online: A = Token, B = AccountUID
/// </summary>
public void GenerateKey(Int32 A, Int32 B)
{
if (m_BufIV == null)
throw new NullReferenceException("IV needs to be generated before generating the key!");
if (m_BufKey != null)
Marshal.FreeHGlobal((IntPtr)m_BufKey);
m_BufKey = (Byte*)Marshal.AllocHGlobal(COSAC_KEY);
Int16 K = COSAC_KEY / 2;
UInt32 tmp1 = 0;
tmp1 = (UInt32)(A + B);
Byte* tmpKey1 = (Byte*)&tmp1;
((Int16*)tmpKey1)[0] ^= 0x4321;
for (SByte i = 0; i < 4; i++)
tmpKey1[3 - i] ^= (Byte)(A >> (24 - (8 * i)));
UInt32 tmp2 = tmp1;
tmp2 *= tmp2;
Byte* tmpKey2 = (Byte*)&tmp2;
for (Int16 i = 0; i < K; i++)
{
m_BufKey[i + 0] = (Byte)(m_BufIV[i + 0] ^ tmpKey1[(i % 4)]);
m_BufKey[i + K] = (Byte)(m_BufIV[i + K] ^ tmpKey2[(i % 4)]);
}
EncryptCounter = 0;
}
/// <summary>
/// Encrypts data with the COSAC algorithm.
/// </summary>
public void Encrypt(Byte* pBuf, Int32 Length)
{
if (pBuf == null)
throw new NullReferenceException("Buffer can't be null!");
if (Length <= 0)
return;
Int16 K = COSAC_IV / 2;
for (Int32 i = 0; i < Length; i++)
{
pBuf[i] ^= (Byte)0xAB;
pBuf[i] = (Byte)(pBuf[i] >> 4 | pBuf[i] << 4);
if (m_BufIV != null)
{
pBuf[i] ^= (Byte)(m_BufIV[(Byte)(EncryptCounter & 0xFF) + 0]);
pBuf[i] ^= (Byte)(m_BufIV[(Byte)(EncryptCounter >> 8) + K]);
}
EncryptCounter++;
}
}
/// <summary>
/// Encrypts data with the COSAC algorithm.
/// </summary>
public void Encrypt(ref Byte[] Buf)
{
Int32 Length = Buf.Length;
fixed (Byte* pBuf = Buf)
{
if (pBuf == null)
throw new NullReferenceException("Buffer can't be null!");
if (Length <= 0)
return;
Int16 K = COSAC_IV / 2;
for (Int32 i = 0; i < Length; i++)
{
pBuf[i] ^= (Byte)0xAB;
pBuf[i] = (Byte)(pBuf[i] >> 4 | pBuf[i] << 4);
if (m_BufIV != null)
{
pBuf[i] ^= (Byte)(m_BufIV[(Byte)(EncryptCounter & 0xFF) + 0]);
pBuf[i] ^= (Byte)(m_BufIV[(Byte)(EncryptCounter >> 8) + K]);
}
EncryptCounter++;
}
}
}
/// <summary>
/// Decrypts data with the COSAC algorithm.
/// </summary>
public void Decrypt(Byte* pBuf, Int32 Length)
{
if (pBuf == null)
throw new NullReferenceException("Buffer can't be null!");
if (Length <= 0)
return;
Int16 K = COSAC_IV / 2;
if (m_BufKey != null)
K = COSAC_KEY / 2;
for (Int32 i = 0; i < Length; i++)
{
pBuf[i] ^= (Byte)0xAB;
pBuf[i] = (Byte)(pBuf[i] >> 4 | pBuf[i] << 4);
if (m_BufKey != null)
{
pBuf[i] ^= (Byte)(m_BufKey[(Byte)(DecryptCounter & 0xFF) + 0]);
pBuf[i] ^= (Byte)(m_BufKey[(Byte)(DecryptCounter >> 8) + K]);
}
else if (m_BufIV != null)
{
pBuf[i] ^= (Byte)(m_BufIV[(Byte)(DecryptCounter & 0xFF) + 0]);
pBuf[i] ^= (Byte)(m_BufIV[(Byte)(DecryptCounter >> 8) + K]);
}
DecryptCounter++;
}
}
/// <summary>
/// Decrypts data with the COSAC algorithm.
/// </summary>
public void Decrypt(ref Byte[] Buf)
{
Int32 Length = Buf.Length;
fixed (Byte* pBuf = Buf)
{
if (pBuf == null)
throw new NullReferenceException("Buffer can't be null!");
if (Length <= 0)
return;
Int16 K = COSAC_IV / 2;
if (m_BufKey != null)
K = COSAC_KEY / 2;
for (Int32 i = 0; i < Length; i++)
{
pBuf[i] ^= (Byte)0xAB;
pBuf[i] = (Byte)(pBuf[i] >> 4 | pBuf[i] << 4);
if (m_BufKey != null)
{
pBuf[i] ^= (Byte)(m_BufKey[(Byte)(DecryptCounter & 0xFF) + 0]);
pBuf[i] ^= (Byte)(m_BufKey[(Byte)(DecryptCounter >> 8) + K]);
}
else if (m_BufIV != null)
{
pBuf[i] ^= (Byte)(m_BufIV[(Byte)(DecryptCounter & 0xFF) + 0]);
pBuf[i] ^= (Byte)(m_BufIV[(Byte)(DecryptCounter >> 8) + K]);
}
DecryptCounter++;
}
}
}
/// <summary>
/// Resets the decrypt and the encrypt counters.
/// </summary>
public void ResetCounters() { DecryptCounter = 0; EncryptCounter = 0; }
}
}
// * ************************************************************
// * * END: cosac.cs *
// * ************************************************************






