private static void RunAsClient() { GonzoNet.PacketHandlers.Register(0x02, false, 0, new OnPacketReceive(PacketHandlers.HandleServerChallenge)); //GonzoNet requires a log output stream to function correctly. This is built in behavior. GonzoNet.Logger.OnMessageLogged += new MessageLoggedDelegate(Logger_OnMessageLogged); StaticStaticDiffieHellman.ExportKey("ClientPublic.dat", PacketHandlers.ClientKey.PublicKey); m_Client = new NetworkClient("127.0.0.1", 12345); m_Client.OnConnected += new OnConnectedDelegate(m_Client_OnConnected); LoginArgsContainer LoginArgs = new LoginArgsContainer(); LoginArgs.Enc = new GonzoNet.Encryption.ARC4Encryptor("test"); LoginArgs.Username = "******"; LoginArgs.Password = "******"; LoginArgs.Client = m_Client; PacketHandlers.GenerateClientIV(); m_Client.Connect(LoginArgs); while (true) { Thread.Sleep(1000); } }
/// <summary> /// A client requested login. /// </summary> /// <param name="Client">NetworkClient instance.</param> /// <param name="Packet">ProcessedPacket instance.</param> public static void InitialClientConnect(NetworkClient Client, ProcessedPacket Packet) { Console.WriteLine("Server receives data - test 1"); PacketStream EncryptedPacket = new PacketStream(0x02, 0); EncryptedPacket.WriteHeader(); ClientPublicKey = Packet.ReadBytes((Packet.ReadByte())); AESEncryptor Enc = (AESEncryptor)Client.ClientEncryptor; Enc.NOnce = Packet.ReadBytes((Packet.ReadByte())); Enc.PublicKey = ClientPublicKey; Enc.PrivateKey = ServerPrivateKey; Client.ClientEncryptor = Enc; //THIS IS IMPORTANT - public key must be derived from private! ServerPublicKey = ServerPrivateKey.PublicKey.ToByteArray(); ChallengeResponse = new byte[16]; m_Random.GetNonZeroBytes(ChallengeResponse); MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); Writer.Write(ChallengeResponse, 0, ChallengeResponse.Length); Writer.Flush(); byte[] EncryptedData = StaticStaticDiffieHellman.Encrypt(ServerPrivateKey, ECDiffieHellmanCngPublicKey.FromByteArray(ClientPublicKey, CngKeyBlobFormat.EccPublicBlob), Enc.NOnce, StreamToEncrypt.ToArray()); EncryptedPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + (1 + ServerPublicKey.Length) + (1 + EncryptedData.Length))); EncryptedPacket.WriteByte((byte)ServerPublicKey.Length); EncryptedPacket.WriteBytes(ServerPublicKey); EncryptedPacket.WriteByte((byte)EncryptedData.Length); EncryptedPacket.WriteBytes(EncryptedData); Client.Send(EncryptedPacket.ToArray()); NetworkFacade.Listener.UpdateClient(Client); Console.WriteLine("Test 1: passed!"); }
private static void RunAsServer() { GonzoNet.PacketHandlers.Register(0x01, false, 0, new OnPacketReceive(PacketHandlers.InitialClientConnect)); GonzoNet.PacketHandlers.Register(0x03, false, 0, new OnPacketReceive(PacketHandlers.HandleChallengeResponse)); //GonzoNet requires a log output stream to function correctly. This is built in behavior. GonzoNet.Logger.OnMessageLogged += new MessageLoggedDelegate(Logger_OnMessageLogged); StaticStaticDiffieHellman.ExportKey("ServerPublic.dat", PacketHandlers.ClientKey.PublicKey); m_Listener.Initialize(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345)); while (true) { Thread.Sleep(1000); } }
/// <summary> /// A client requested login. /// </summary> /// <param name="Client">NetworkClient instance.</param> /// <param name="Packet">ProcessedPacket instance.</param> public static void InitialClientConnect(NetworkClient Client, ProcessedPacket Packet) { Console.WriteLine("Server receives data - test 1"); //AES is used to encrypt all further communication between client and server. AesCryptoServiceProvider AesCrypto = new AesCryptoServiceProvider(); AesCrypto.GenerateKey(); AesCrypto.GenerateIV(); AES AesEncryptor = new AES(AesCrypto.Key, AesCrypto.IV); SessionKey = AesCrypto.Key; IV = AesCrypto.IV; Guid Nonce = new Guid(Packet.ReadPascalString()); //Username would normally be used to lookup client's public key in DB (only time such a use is valid). string Username = Packet.ReadPascalString(); ECDiffieHellmanPublicKey ClientPub = StaticStaticDiffieHellman.ImportKey("ClientPublic.dat"); PacketStream EncryptedPacket = new PacketStream(0x02, 0); EncryptedPacket.WriteHeader(); MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); Writer.Write((byte)ChallengeResponse.ToByteArray().Length); Writer.Write(ChallengeResponse.ToByteArray(), 0, ChallengeResponse.ToByteArray().Length); Writer.Write((byte)SessionKey.Length); Writer.Write(SessionKey, 0, SessionKey.Length); Writer.Write((byte)IV.Length); Writer.Write(IV, 0, IV.Length); Writer.Flush(); byte[] EncryptedData = StaticStaticDiffieHellman.Encrypt(ServerKey, ClientPub, Nonce.ToByteArray(), StreamToEncrypt.ToArray()); EncryptedPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1 + EncryptedData.Length)); EncryptedPacket.WriteByte((byte)EncryptedData.Length); EncryptedPacket.Write(EncryptedData, 0, EncryptedData.Length); Client.Send(EncryptedPacket.ToArray()); Console.WriteLine("Test 1: passed!"); }
/// <summary> /// Initial response from server to client. /// </summary> /// <param name="Client">A NetworkClient instance.</param> /// <param name="Packet">A ProcessedPacket instance.</param> public static void HandleServerChallenge(NetworkClient Client, ProcessedPacket Packet) { Console.WriteLine("Client receives encrypted data - test 2"); byte[] PacketBuf = new byte[Packet.ReadByte()]; Packet.Read(PacketBuf, 0, (int)PacketBuf.Length); ECDiffieHellmanPublicKey ServerPub = StaticStaticDiffieHellman.ImportKey("ServerPublic.dat"); MemoryStream DecryptedStream = new MemoryStream(StaticStaticDiffieHellman.Decrypt(ClientKey, ServerPub, ClientNOnce.ToByteArray(), PacketBuf)); BinaryReader Reader = new BinaryReader(DecryptedStream); Guid ChallengeResponse = new Guid(Reader.ReadBytes(Reader.ReadByte())); SessionKey = Reader.ReadBytes(Reader.ReadByte()); IV = Reader.ReadBytes(Reader.ReadByte()); //Yay, we have key and IV, we can now start encryption with AES! AES AesEncryptor = new AES(SessionKey, IV); PacketStream EncryptedPacket = new PacketStream(0x03, 0); EncryptedPacket.WriteHeader(); MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); Writer.Write((byte)ChallengeResponse.ToByteArray().Length); Writer.Write(ChallengeResponse.ToByteArray(), 0, ChallengeResponse.ToByteArray().Length); //Encrypt data using key and IV from server, hoping that it'll be decrypted correctly at the other end... byte[] EncryptedData = AesEncryptor.Encrypt(StreamToEncrypt.ToArray()); EncryptedPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + EncryptedData.Length + 1)); EncryptedPacket.WriteByte((byte)EncryptedData.Length); EncryptedPacket.Write(EncryptedData, 0, EncryptedData.Length); Client.Send(EncryptedPacket.ToArray()); Console.WriteLine("Test 2: passed!"); }
/// <summary> /// Initial response from server to client. /// </summary> /// <param name="Client">A NetworkClient instance.</param> /// <param name="Packet">A ProcessedPacket instance.</param> public static void HandleServerChallenge(NetworkClient Client, ProcessedPacket Packet) { Console.WriteLine("Client receives encrypted data - test 2"); ServerPublicKey = Packet.ReadBytes(Packet.ReadByte()); byte[] EncryptedData = Packet.ReadBytes(Packet.ReadByte()); AESEncryptor Enc = (AESEncryptor)Client.ClientEncryptor; Enc.PublicKey = ServerPublicKey; Client.ClientEncryptor = Enc; NetworkFacade.Client.ClientEncryptor = Enc; ECDiffieHellmanCng PrivateKey = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs.PrivateKey; byte[] NOnce = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs.NOnce; byte[] ChallengeResponse = StaticStaticDiffieHellman.Decrypt(PrivateKey, ECDiffieHellmanCngPublicKey.FromByteArray(ServerPublicKey, CngKeyBlobFormat.EccPublicBlob), NOnce, EncryptedData); MemoryStream StreamToEncrypt = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(StreamToEncrypt); Writer.Write((byte)ChallengeResponse.Length); Writer.Write(ChallengeResponse, 0, ChallengeResponse.Length); Writer.Write(Client.ClientEncryptor.Username); Writer.Write((byte)PasswordHash.Length); Writer.Write(PasswordHash); Writer.Flush(); Client.SendEncrypted(0x03, StreamToEncrypt.ToArray()); Console.WriteLine("Test 2: passed!"); }