Might as well post it here. I'm trying to upgrade the password encryption from Hybrid's 5135 source to be used with a 5250 client but it's kinda giving me a headache.
Well I'm confused.
public string ToString(LoginRequest Request)
{
msvcrt.msvcrt.srand(this.GeneratedSeed);
var rc5Key = new byte[0x10];
for (int i = 0; i < 0x10; i++)
rc5Key[i] = (byte)msvcrt.msvcrt.rand();
string Password1 = Encoding.ASCII.GetString(Request.Packet, 132, 16).Trim((char)0x0000);
this.EncryptedPassword = new byte[16];
Buffer.BlockCopy(Request.Packet, 132, this.EncryptedPassword, 0, 16);
return Encoding.ASCII.GetString(
(new ConquerPasswordCryptpographer(Request.Account).Decrypt(
(new RC5(rc5Key)).Decrypt(this.EncryptedPassword))));
}
Kinshi:
Code:
public String DecryptPassword(UInt32 key, String account, Byte[] packet)
{
Native.srand((int)key);
var rc5Key = new byte[0x10];
for (int i = 0; i < 0x10; i++)
rc5Key[i] = (byte)Native.rand();
Byte[] originalPassword = new byte[16];
Buffer.BlockCopy(packet, 132, originalPassword, 0, 16);
return Encoding.ASCII.GetString(
(new ConquerPasswordCryptpographer(account).Decrypt(
(new RC5(rc5Key)).Decrypt(originalPassword))));
}
What I got after trying to convert their decrypting code:
public string DecryptPassword(LoginPacket Request)
{
MSVCRT.srand(Seed);
var rc5Key = new byte[0x10];
for (int i = 0; i < 0x10; i++)
rc5Key[i] = (byte)MSVCRT.rand();
byte[] EncryptedPassword = new byte[16];
[b]Can't seem to find an equivalent for this in the source[/b] Buffer.BlockCopy(Request.Packet, 132, EncryptedPassword, 0, 16);
return Encoding.ASCII.GetString(
(new ConquerPasswordCryptpographer(Request.User).Decrypt(
(new RC5(rc5Key)).Decrypt(EncryptedPassword))));
}
So can I get some help with the password decrypting code?
//edit I guess the title should be decryption... oh well.
string Pass;
msvcrt.msvcrt.srand(Client.PassSeed);
var rc5Key = new byte[0x10];
for (int i = 0; i < 0x10; i++)
rc5Key[i] = (byte)msvcrt.msvcrt.rand();
ConquerPasswordCryptpographer A = new ConquerPasswordCryptpographer(User);
Encryption.RC5 B = new Encryption.RC5(rc5Key);
Pass = Encoding.ASCII.GetString(
(new ConquerPasswordCryptpographer(User).Decrypt(new Encryption.RC5(rc5Key).Decrypt(Password))));
Pass = Pass.Replace("\0", "");
I just use the released liberate cryptography dll, msvcrt dll and then the following pass crypt class.
Code:
public sealed class RC5Exception : Exception
{
public RC5Exception(string message) : base(message) { }
}
public sealed class RC5
{
private readonly uint[] _bufKey = new uint[4];
private readonly uint[] _bufSub = new uint[26];
public RC5(byte[] data)
{
if (data.Length != 16) throw new RC5Exception("Invalid data length. Must be 16 bytes");
const uint p32 = 0xB7E15163;
const uint q32 = 0x61C88647;
uint offsetA = 0, offsetB = 0, A = 0, B = 0;
for (int i = 0; i < 4; i++)
_bufKey[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
_bufSub[0] = p32;
for (int i = 1; i < 26; i++)
{
_bufSub[i] = _bufSub[i - 1] - q32;
}
for (int s = 1; s <= 78; s++)
{
_bufSub[offsetA] = LeftRotate(_bufSub[offsetA] + A + B, 3);
A = _bufSub[offsetA];
offsetA = (offsetA + 1) % 0x1A;
_bufKey[offsetB] = LeftRotate(_bufKey[offsetB] + A + B, (int)(A + B));
B = _bufKey[offsetB];
offsetB = (offsetB + 1) % 4;
}
}
public byte[] Decrypt(byte[] data)
{
if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
int nLen = data.Length / 8 * 8;
if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
uint[] bufData = new uint[data.Length / 4];
for (int i = 0; i < data.Length / 4; i++)
bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
for (int i = 0; i < nLen / 8; i++)
{
uint ld = bufData[2 * i];
uint rd = bufData[2 * i + 1];
for (int j = 12; j >= 1; j--)
{
rd = RightRotate((rd - _bufSub[2 * j + 1]), (int)ld) ^ ld;
ld = RightRotate((ld - _bufSub[2 * j]), (int)rd) ^ rd;
}
uint B = rd - _bufSub[1];
uint A = ld - _bufSub[0];
bufData[2 * i] = A;
bufData[2 * i + 1] = B;
}
byte[] result = new byte[bufData.Length * 4];
for (int i = 0; i < bufData.Length; i++)
{
result[i * 4] = (byte)bufData[i];
result[i * 4 + 1] = (byte)(bufData[i] >> 8);
result[i * 4 + 2] = (byte)(bufData[i] >> 16);
result[i * 4 + 3] = (byte)(bufData[i] >> 24);
}
return result;
}
public byte[] Encrypt(byte[] data)
{
if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
int nLen = data.Length / 8 * 8;
if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
uint[] bufData = new uint[data.Length / 4];
for (int i = 0; i < data.Length / 4; i++)
bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
for (int i = 0; i < nLen / 8; i++)
{
uint A = bufData[i * 2];
uint B = bufData[i * 2 + 1];
uint le = A + _bufSub[0];
uint re = B + _bufSub[1];
for (int j = 1; j <= 12; j++)
{
le = LeftRotate((le ^ re), (int)re) + _bufSub[j * 2];
re = LeftRotate((re ^ le), (int)le) + _bufSub[j * 2 + 1];
}
bufData[i * 2] = le;
bufData[i * 2 + 1] = re;
}
byte[] result = new byte[bufData.Length * 4];
for (int i = 0; i < bufData.Length; i++)
{
result[i * 4] = (byte)bufData[i];
result[i * 4 + 1] = (byte)(bufData[i] >> 8);
result[i * 4 + 2] = (byte)(bufData[i] >> 16);
result[i * 4 + 3] = (byte)(bufData[i] >> 24);
}
return result;
}
internal static uint LeftRotate(uint dwVar, int dwOffset)
{
return (dwVar << (dwOffset & 0x1F) | dwVar >> 0x20 - (dwOffset & 0x1F));
}
internal static uint RightRotate(uint dwVar, int dwOffset)
{
return (dwVar >> (dwOffset & 0x1F) | dwVar << 0x20 - (dwOffset & 0x1F));
}
}
string Pass;
msvcrt.msvcrt.srand(Client.PassSeed);
var rc5Key = new byte[0x10];
for (int i = 0; i < 0x10; i++)
rc5Key[i] = (byte)msvcrt.msvcrt.rand();
ConquerPasswordCryptpographer A = new ConquerPasswordCryptpographer(User);
Encryption.RC5 B = new Encryption.RC5(rc5Key);
Pass = Encoding.ASCII.GetString(
(new ConquerPasswordCryptpographer(User).Decrypt(new Encryption.RC5(rc5Key).Decrypt(Password))));
Pass = Pass.Replace("\0", "");
I just use the released liberate cryptography dll, msvcrt dll and then the following pass crypt class.
Code:
public sealed class RC5Exception : Exception
{
public RC5Exception(string message) : base(message) { }
}
public sealed class RC5
{
private readonly uint[] _bufKey = new uint[4];
private readonly uint[] _bufSub = new uint[26];
public RC5(byte[] data)
{
if (data.Length != 16) throw new RC5Exception("Invalid data length. Must be 16 bytes");
const uint p32 = 0xB7E15163;
const uint q32 = 0x61C88647;
uint offsetA = 0, offsetB = 0, A = 0, B = 0;
for (int i = 0; i < 4; i++)
_bufKey[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
_bufSub[0] = p32;
for (int i = 1; i < 26; i++)
{
_bufSub[i] = _bufSub[i - 1] - q32;
}
for (int s = 1; s <= 78; s++)
{
_bufSub[offsetA] = LeftRotate(_bufSub[offsetA] + A + B, 3);
A = _bufSub[offsetA];
offsetA = (offsetA + 1) % 0x1A;
_bufKey[offsetB] = LeftRotate(_bufKey[offsetB] + A + B, (int)(A + B));
B = _bufKey[offsetB];
offsetB = (offsetB + 1) % 4;
}
}
public byte[] Decrypt(byte[] data)
{
if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
int nLen = data.Length / 8 * 8;
if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
uint[] bufData = new uint[data.Length / 4];
for (int i = 0; i < data.Length / 4; i++)
bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
for (int i = 0; i < nLen / 8; i++)
{
uint ld = bufData[2 * i];
uint rd = bufData[2 * i + 1];
for (int j = 12; j >= 1; j--)
{
rd = RightRotate((rd - _bufSub[2 * j + 1]), (int)ld) ^ ld;
ld = RightRotate((ld - _bufSub[2 * j]), (int)rd) ^ rd;
}
uint B = rd - _bufSub[1];
uint A = ld - _bufSub[0];
bufData[2 * i] = A;
bufData[2 * i + 1] = B;
}
byte[] result = new byte[bufData.Length * 4];
for (int i = 0; i < bufData.Length; i++)
{
result[i * 4] = (byte)bufData[i];
result[i * 4 + 1] = (byte)(bufData[i] >> 8);
result[i * 4 + 2] = (byte)(bufData[i] >> 16);
result[i * 4 + 3] = (byte)(bufData[i] >> 24);
}
return result;
}
public byte[] Encrypt(byte[] data)
{
if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
int nLen = data.Length / 8 * 8;
if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
uint[] bufData = new uint[data.Length / 4];
for (int i = 0; i < data.Length / 4; i++)
bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
for (int i = 0; i < nLen / 8; i++)
{
uint A = bufData[i * 2];
uint B = bufData[i * 2 + 1];
uint le = A + _bufSub[0];
uint re = B + _bufSub[1];
for (int j = 1; j <= 12; j++)
{
le = LeftRotate((le ^ re), (int)re) + _bufSub[j * 2];
re = LeftRotate((re ^ le), (int)le) + _bufSub[j * 2 + 1];
}
bufData[i * 2] = le;
bufData[i * 2 + 1] = re;
}
byte[] result = new byte[bufData.Length * 4];
for (int i = 0; i < bufData.Length; i++)
{
result[i * 4] = (byte)bufData[i];
result[i * 4 + 1] = (byte)(bufData[i] >> 8);
result[i * 4 + 2] = (byte)(bufData[i] >> 16);
result[i * 4 + 3] = (byte)(bufData[i] >> 24);
}
return result;
}
internal static uint LeftRotate(uint dwVar, int dwOffset)
{
return (dwVar << (dwOffset & 0x1F) | dwVar >> 0x20 - (dwOffset & 0x1F));
}
internal static uint RightRotate(uint dwVar, int dwOffset)
{
return (dwVar >> (dwOffset & 0x1F) | dwVar << 0x20 - (dwOffset & 0x1F));
}
}
The thing is that I don't know how to read from the packet in fact that is the only problem I have.
//edit Incase you need it:
public unsafe struct LoginPacket
{
public const ushort cSize = 0x114;
public const ushort cType = 0x43E;
public ushort Size;
public ushort Type;
public fixed sbyte szUser[128];
public fixed uint szPassword[32];
public fixed sbyte szServer[16];
public string User { get { fixed (sbyte* ptr = szUser) { return new string(ptr); } } }
public string Server { get { fixed (sbyte* ptr = szServer) { return new string(ptr); } } }
public string Password { get { fixed (uint* ptr = szPassword) { return new string((sbyte*)ptr); } } }
}
#1: use buffer block copy to copy from the destination array into a new one.
#2: use a packet reading method from some other source or write your own...
Here's the readbytes method tannel made that iirc is what I used in my proxy.
Code:
public byte[] ReadBytes(int Count)
{
byte[] Val = new byte[Count];
Buffer.BlockCopy(PData, Position, Val, 0, Count);
Position += Count;
return Val;
}
Therefor you just readbytes the password section of the login packet and run that through the method.
Very simple really... just find the password offset in the packet and you're good to go.
<edit>
taking a glance at your password thing you are trying to read it as a string... that's not what you want to do.
What you need to be doing is reading the bytes of the password into an array, decrypting that array using password crypt and saving the output into a password string.
#1: use buffer block copy to copy from the destination array into a new one.
#2: use a packet reading method from some other source or write your own...
Here's the readbytes method tannel made that iirc is what I used in my proxy.
Code:
public byte[] ReadBytes(int Count)
{
byte[] Val = new byte[Count];
Buffer.BlockCopy(PData, Position, Val, 0, Count);
Position += Count;
return Val;
}
Therefor you just readbytes the password section of the login packet and run that through the method.
Very simple really... just find the password offset in the packet and you're good to go.
<edit>
taking a glance at your password thing you are trying to read it as a string... that's not what you want to do.
What you need to be doing is reading the bytes of the password into an array, decrypting that array using password crypt and saving the output into a password string.
Well about Buffer.BlockCopy, I started but I simply couldn't find what had to be the first value (called Array src or in your case PData) which kinda had me confused.
Well about Buffer.BlockCopy, I started but I simply couldn't find what had to be the first value (called Array src or in your case PData) which kinda had me confused.
Array Source perhaps?
Seriously, how can that not be the easiest thing to understand?
(Source array (copy from main packet), Source offset(where to start reading from the main packet), Destination Array (where you are copying to. The password array), Destination Offset (where to start writing in destination packet), Count (how many bytes to copy over))
public unsafe struct LoginPacket
{
public const ushort cSize = 0x114;
public const ushort cType = 0x43E;
public ushort Size;
public ushort Type;
public fixed sbyte szUser[128];
public fixed uint szPassword[32];
public fixed sbyte szServer[16];
public string User { get { fixed (sbyte* ptr = szUser) { return new string(ptr); } } }
public string Server { get { fixed (sbyte* ptr = szServer) { return new string(ptr); } } }
public string Password { get { fixed (uint* ptr = szPassword) { return new string((sbyte*)ptr); } } }
}
The thing is that I don't know how to read from the packet in fact that is the only problem I have.
//edit Incase you need it:
You say you don't know how to copy from the packet... I just said you make a array to store the password and then block copy to copy the relevant bytes into it and then run the password array through the decryption method to return a string.
Your problem is that at least in the first code you posted it appears as though you are using pointers to read the bytes and make them into a string format.
Keep in mind it's 16 bytes just like every single other non counted string in conquer lol.
You say you don't know how to copy from the packet... I just said you make a array to store the password and then block copy to copy the relevant bytes into it and then run the password array through the decryption method to return a string.
Your problem is that at least in the first code you posted it appears as though you are using pointers to read the bytes and make them into a string format.
Keep in mind it's 16 bytes just like every single other non counted string in conquer lol.
Well I can't really do anything about the pointer usage since it's what Hybrid coded and I don't know how to change it.
Quote:
Originally Posted by samehvan
i think the problem is with the szUser , the value u should receive for it is only 16 bytes starting from offset 4
No it's not the User, I printed it to the console and it showed the correct User.
//edit With:
Client.Password = Client.Decrypt(login->User, Received);
And entering password: 123456789
and the console prints: #<"%♀'$&! which are indeed 9 characters but not the correct ones.
[HELP] Password encryption 12/26/2009 - CO2 Private Server - 27 Replies What Password encryption does conquer have? i want to code register script and don`t know encryption for password,its not md5.
AuthServer password encryption 04/26/2009 - CO2 Private Server - 1 Replies Well thought it would fit in this section.
Most of the sources I seen works this way: the first time an account login, it takes the "encrypted" password received and set it in the database. I've been trying to figure the encryption used, but with no success, my ASM skills just sucks.
So, could anyone decent with assembler/debugging help me with this?
CO password encryption 11/30/2008 - Conquer Online 2 - 3 Replies Was it ever released? I know it was hiding in dev section for some time but I don't know if it ever got out. If it has, a friendly link to where to? Or if not, maybe an explanation? It's quite a weird encryption at first glance. Thanks in advance.
<hr>Append on Apr 6 2007, 20:50<hr> As much as people would probably not like to help out, I'm trying to get stuff going for the benefit of the community : [ I'm doing a c++ server emu and so far everything's going smooth except the password...
Conquer Password Encryption? 12/25/2007 - Conquer Online 2 - 4 Replies Me and my bro are currently making a private server and we need help with the password encryption. Any help would be greatly appreciated. :D