Hey,
This is what I think a much cleaner KeyExchange, and yes it's using SSL.
KeyExchange.cs
ServerKeyPacket.cs
ClientKeyPacket.cs
Usage:
Upon connection to the game server
How I handle it:
Enjoy.
This is what I think a much cleaner KeyExchange, and yes it's using SSL.
KeyExchange.cs
Code:
using OpenSSL;
using PoisonCO.Core.PacketProcessor.Structures;
namespace PoisonCO.Game.Crypto
{
public class KeyExchange
{
public DH Exchange;
private readonly string _p, _g;
public ServerKeyPacket ServerKeyPacket;
public byte[] ClientIV = new byte[8];
public byte[] ServerIV = new byte[8];
private GameCryptographer _cryptography;
public KeyExchange()
{
_p = "E7A69EBDF105F2A6BBDEAD7E798F76A209AD73FB466431E2E7352ED262F8C558F10BEFEA977DE9E21DCEE9B04D245F300ECCBBA03E72630556D011023F9E857F";
_g = "05";
Exchange = new DH(BigNumber.FromHexString(_p), BigNumber.FromHexString(_g));
Exchange.GenerateKeys();
InitalizeKeyPacket(ServerIV, ClientIV, _p, _g, Exchange.PublicKey.ToHexString());
}
public void HandleClientKeyPacket(string pKey, GameClient client)
{
_cryptography = client.GameCrypto;
_cryptography.SetKey(ComputeKey(pKey));
SetIVs(_cryptography);
}
public void SetIVs(GameCryptographer crypto)
{
crypto.SetIvs(ClientIV, ServerIV);
}
public byte[] ComputeKey(string pKey)
{
return Exchange.ComputeKey(BigNumber.FromHexString(pKey));
}
public void InitalizeKeyPacket(byte[] serverIV1, byte[] serverIV2, string p, string g, string serverPublicKey)
{
ServerKeyPacket = new ServerKeyPacket
{
ServerPublicKey = serverPublicKey,
ServerIV1 = serverIV1,
ServerIV2 = serverIV2,
P = p,
G = g
};
}
}
}
Code:
using System;
using System.IO;
namespace PoisonCO.Core.PacketProcessor.Structures
{
public class ServerKeyPacket
{
private byte[] _serverIV1, _serverIV2;
private string _p, _g, _serverPublicKey;
public ServerKeyPacket()
{
}
public byte[] ServerIV1
{
get { return _serverIV1; }
set { _serverIV1 = value; }
}
public byte[] ServerIV2
{
get { return _serverIV2; }
set { _serverIV2 = value; }
}
public string P
{
get { return _p; }
set { _p = value; }
}
public string G
{
get { return _g; }
set { _g = value; }
}
public string ServerPublicKey
{
get { return _serverPublicKey; }
set { _serverPublicKey = value; }
}
public byte[] ToBytes()
{
const int padLen = 11;
const int junkLen = 12;
const string tqs = "TQServer";
byte[] packet;
var ms = new MemoryStream();
var pad = new byte[padLen];
Kernel.Random.NextBytes(pad);
var junk = new byte[junkLen];
Kernel.Random.NextBytes(junk);
var size = 47 + _p.Length + _g.Length + _serverPublicKey.Length + 12 + 8 + 8;
using (var br = new BinaryWriter(ms))
{
br.Write(pad);
br.Write(size - padLen);
br.Write((UInt32)junkLen);
br.Write(junk);
br.Write((UInt32)_serverIV2.Length);
br.Write(_serverIV2);
br.Write((UInt32)_serverIV1.Length);
br.Write(_serverIV1);
br.Write((UInt32)_p.ToCharArray().Length);
foreach (var fP in _p.ToCharArray())
{
br.BaseStream.WriteByte((byte)fP);
}
br.Write((UInt32)_g.ToCharArray().Length);
foreach (var fG in _g.ToCharArray())
{
br.BaseStream.WriteByte((byte)fG);
}
br.Write((UInt32)_serverPublicKey.ToCharArray().Length);
foreach (var spk in _serverPublicKey.ToCharArray())
{
br.BaseStream.WriteByte((byte)spk);
}
foreach (var tq in tqs.ToCharArray())
{
br.BaseStream.WriteByte((byte)tq);
}
packet = ms.ToArray();
ms.Close();
}
return packet;
}
}
}
Code:
using System.IO;
using System.Text;
namespace PoisonCO.Core.PacketProcessor.Structures
{
public class ClientKeyPacket
{
private byte[] _junk1, _junk3;
private uint _junk2;
private int _junkLength, _length;
private byte[] _pKey;
public ClientKeyPacket(byte[] data)
{
var stream = new MemoryStream(data);
using (var rdr = new BinaryReader(stream))
{
//Junk
_junk1 = rdr.ReadBytes(7);
_junk2 = rdr.ReadUInt32();
_junkLength = rdr.ReadInt32();
_junk3 = rdr.ReadBytes(_junkLength);
//Useful stuff
_length = rdr.ReadInt32();
_pKey = rdr.ReadBytes(_length);
stream.Close();
}
}
public byte[] Junk1
{
get { return _junk1; }
}
public uint Junk2
{
get { return _junk2; }
}
public int JunkLength
{
get { return _junkLength; }
}
public byte[] Junk3
{
get { return _junk3; }
}
public int Length
{
get { return _length; }
}
public string PublicKey
{
get { return Encoding.ASCII.GetString(_pKey); }
}
}
}
Upon connection to the game server
Code:
Client.Send(Client.Exchange.ServerKeyPacket.ToBytes());
Code:
switch (Client.IsExchanging)
{
case false:
{
Client.IsExchanging = true;
var pkt = new ClientKeyPacket(Packet);
Client.Exchange.HandleClientKeyPacket(pkt.PublicKey, Client);
break;
}
case true:
{
Core.PacketProcessor.Process.PacketSplitter(Packet, Client);
break;
}
}