private void FinializeServerEncryption(EncryptionKeyResponsePacket encryptionKeyResponsePacket) { // Here, we have all the details we need to initialize our // proxy<->server crypto stream. This happens *after* we have // already completed the crypto handshake with the client. // Wrap the server stream in a crypto stream ServerStream = new NetworkManager(new AesStream(Server, ServerSharedKey)); Log.Write("Encrypted server connection established."); // Write the response. This is the first encrypted packet // sent to the client. The correct response is to send // an 0xFC EncryptionKeyResponse with both fields as empty // arrays. var response = new EncryptionKeyResponsePacket { SharedSecret = new byte[0], VerificationToken = new byte[0] }; ClientStream.WritePacket(response, Craft.Net.PacketDirection.Clientbound); Client.Flush(); // Wrap the client stream in a crypto stream ClientStream = new NetworkManager(new AesStream(Client, ClientSharedKey)); Log.Write("Encrypted client connection established."); // And now we're done with encryption and everything can // continue normally. }
private bool FinializeClientEncryption(EncryptionKeyResponsePacket encryptionKeyResponsePacket) { // Here, we need to prepare everything to enable client<->proxy // encryption, but we can't turn it on quite yet. if (Settings.AuthenticateClients) { // Do authentication // Create a hash for session verification AsnKeyBuilder.AsnMessage encodedKey = AsnKeyBuilder.PublicKeyToX509(ServerKey); byte[] shaData = Encoding.UTF8.GetBytes(ClientAuthenticationHash) .Concat(ClientSharedKey) .Concat(encodedKey.GetBytes()).ToArray(); string hash = Cryptography.JavaHexDigest(shaData); var client = new WebClient(); var result = client.DownloadString(string.Format("http://session.minecraft.net/game/checkserver.jsp?user={0}&serverId={1}", PlayerName, hash)); if (result != "YES") { Log.Write("Failed to authenticate " + PlayerName + "!"); ServerStream.WritePacket(new DisconnectPacket("Failed to authenticate!"), Craft.Net.PacketDirection.Serverbound); ClientStream.WritePacket(new DisconnectPacket("Failed to authenticate!"), Craft.Net.PacketDirection.Clientbound); Server.Flush(); Client.Flush(); return(false); } } // Send unencrypted response ServerStream.WritePacket(ServerEncryptionResponse, Craft.Net.PacketDirection.Serverbound); Server.Flush(); // We wait for the server to respond, then set up encryption // for both sides of the connection. ServerStream.BaseStream = new AesStream(Server, ServerSharedKey); return(true); }
private void UpdateServer() { while (Server.DataAvailable) { var packet = ServerStream.ReadPacket(Craft.Net.PacketDirection.Clientbound); Log.LogPacket(packet, false); if (packet is EncryptionKeyRequestPacket) { InitializeEncryption((EncryptionKeyRequestPacket)packet); } else { var eventArgs = new IncomingPacketEventArgs(packet, false); if (IncomingPacket != null) { IncomingPacket(this, eventArgs); } lock (Client) { if (!eventArgs.Handled) { ClientStream.WritePacket(packet, Craft.Net.PacketDirection.Clientbound); } Client.Flush(); } if (packet is DisconnectPacket) { Console.WriteLine("Server disconnected: " + ((DisconnectPacket)packet).Reason); if (ConnectionClosed != null) { ConnectionClosed(this, null); } Worker.Abort(); } } } }