Пример #1
1
        public static void EncryptionKeyRequest(MinecraftClient client, IPacket _packet)
        {
            var packet = (EncryptionKeyRequestPacket)_packet;
            var random = RandomNumberGenerator.Create();
            client.SharedSecret = new byte[16];
            random.GetBytes(client.SharedSecret); // Generate a secure AES key

            if (packet.ServerId != "-") // Online mode
            {
                // Authenticate with minecraft.net
                var data = Encoding.ASCII.GetBytes(packet.ServerId)
                    .Concat(client.SharedSecret)
                    .Concat(packet.PublicKey).ToArray();
                var hash = Cryptography.JavaHexDigest(data);
                var webClient = new WebClient();
                string result = webClient.DownloadString("http://session.minecraft.net/game/joinserver.jsp?user="******"&sessionId=" + Uri.EscapeUriString(client.Session.SessionId) +
                    "&serverId=" + Uri.EscapeUriString(hash));
                if (result != "OK")
                    LogProvider.Log("Unable to verify session: " + result);
            }

            var parser = new AsnKeyParser(packet.PublicKey);
            var key = parser.ParseRSAPublicKey();

            // Encrypt shared secret and verification token
            var crypto = new RSACryptoServiceProvider();
            crypto.ImportParameters(key);
            var encryptedSharedSecret = crypto.Encrypt(client.SharedSecret, false);
            var encryptedVerification = crypto.Encrypt(packet.VerificationToken, false);
            var response = new EncryptionKeyResponsePacket(encryptedSharedSecret, encryptedVerification);
            client.SendPacket(response);
        }
Пример #2
0
        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.
        }
Пример #3
0
        public static void EncryptionKeyRequest(MinecraftClient client, IPacket _packet)
        {
            var packet = (EncryptionKeyRequestPacket)_packet;
            var random = RandomNumberGenerator.Create();

            client.SharedSecret = new byte[16];
            random.GetBytes(client.SharedSecret); // Generate a secure AES key

            if (packet.ServerId != "-")           // Online mode
            {
                // Authenticate with minecraft.net
                if (!client.Session.OnlineMode)
                {
                    throw new AuthenticationException("Server is in online mode, but client is in offline mode.");
                }
                var data = Encoding.ASCII.GetBytes(packet.ServerId)
                           .Concat(client.SharedSecret)
                           .Concat(packet.PublicKey).ToArray();
                var    hash      = Cryptography.JavaHexDigest(data);
                var    webClient = new WebClient();
                string result    = webClient.DownloadString("http://session.minecraft.net/game/joinserver.jsp?user="******"&sessionId=" + Uri.EscapeUriString(client.Session.SessionId) +
                                                            "&serverId=" + Uri.EscapeUriString(hash));
                if (result != "OK")
                {
                    // TODO
                }
            }

            var parser = new AsnKeyParser(packet.PublicKey);
            var key    = parser.ParseRSAPublicKey();

            // Encrypt shared secret and verification token
            var crypto = new RSACryptoServiceProvider();

            crypto.ImportParameters(key);
            var encryptedSharedSecret = crypto.Encrypt(client.SharedSecret, false);
            var encryptedVerification = crypto.Encrypt(packet.VerificationToken, false);
            var response = new EncryptionKeyResponsePacket(encryptedSharedSecret, encryptedVerification);

            client.SendPacket(response);
            client.FlushPackets();
            client.NetworkManager.BaseStream = new AesStream(client.NetworkStream, client.SharedSecret);
        }
Пример #4
0
        public static void EncryptionKeyRequest(MinecraftClient client, IPacket _packet)
        {
            var packet = (EncryptionKeyRequestPacket)_packet;
            var random = RandomNumberGenerator.Create();

            client.SharedSecret = new byte[16];
            random.GetBytes(client.SharedSecret);                           // Generate a secure AES key

            if (packet.ServerId != "-" && client.Session.SessionId != null) // Online mode
            {
                // Authenticate with minecraft.net
                var data = Encoding.ASCII.GetBytes(packet.ServerId)
                           .Concat(client.SharedSecret)
                           .Concat(packet.PublicKey).ToArray();
                var    hash      = Cryptography.JavaHexDigest(data);
                var    webClient = new WebClient();
                string result    = webClient.DownloadString("http://session.minecraft.net/game/joinserver.jsp?user="******"&sessionId=" + Uri.EscapeUriString(client.Session.SessionId) +
                                                            "&serverId=" + Uri.EscapeUriString(hash));
                if (result != "OK")
                {
                    LogProvider.Log("Unable to verify session: " + result);
                }
            }

            var parser = new AsnKeyParser(packet.PublicKey);
            var key    = parser.ParseRSAPublicKey();

            // Encrypt shared secret and verification token
            var crypto = new RSACryptoServiceProvider();

            crypto.ImportParameters(key);
            var encryptedSharedSecret = crypto.Encrypt(client.SharedSecret, false);
            var encryptedVerification = crypto.Encrypt(packet.VerificationToken, false);
            var response = new EncryptionKeyResponsePacket(encryptedSharedSecret, encryptedVerification);

            client.SendPacket(response);
        }
Пример #5
0
        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);
        }
Пример #6
0
        private void InitializeEncryption(EncryptionKeyRequestPacket packet)
        {
            // We have to hijack the encryption here to be able to sniff the
            // connection. What we do is set up two unrelated crypto streams,
            // one for the server, one for the client. We actually act a bit
            // more like a real client or a real server in this particular
            // stage of the connection, because we generate a shared secret
            // as a client and a public key as a server, and liase with each
            // end of the connection without tipping them off to this. After
            // this is done, we wrap the connection in an AesStream and
            // everything works fine.

            // Interact with the server (acting as a client)

            // Generate our shared secret
            var secureRandom = RandomNumberGenerator.Create();

            ServerSharedKey = new byte[16];
            secureRandom.GetBytes(ServerSharedKey);

            // Parse the server public key
            var parser = new AsnKeyParser(packet.PublicKey);
            var key    = parser.ParseRSAPublicKey();

            // Encrypt shared secret and verification token
            var crypto = new RSACryptoServiceProvider();

            crypto.ImportParameters(key);
            byte[] encryptedSharedSecret = crypto.Encrypt(ServerSharedKey, false);
            byte[] encryptedVerification = crypto.Encrypt(packet.VerificationToken, false);

            // Create an 0xFC response to give the server
            ServerEncryptionResponse = new EncryptionKeyResponsePacket
            {
                SharedSecret      = encryptedSharedSecret,
                VerificationToken = encryptedVerification
            };

            // Authenticate with minecraft.net if need be
            if (packet.ServerId != "-")
            {
                try
                {
                    var session = Session.DoLogin(Settings.Username, Settings.Password);
                    // Generate session hash
                    byte[] hashData = Encoding.ASCII.GetBytes(packet.ServerId)
                                      .Concat(ServerSharedKey)
                                      .Concat(packet.PublicKey).ToArray();
                    var    hash      = Cryptography.JavaHexDigest(hashData);
                    var    webClient = new WebClient();
                    string result    = webClient.DownloadString("http://session.minecraft.net/game/joinserver.jsp?user="******"&sessionId=" + Uri.EscapeUriString(session.SessionId) +
                                                                "&serverId=" + Uri.EscapeUriString(hash));
                    if (result != "OK")
                    {
                        Console.WriteLine("Warning: Unable to login as user " + Settings.Username + ": " + result);
                    }
                    Console.WriteLine("(Session ID is {0})", session.SessionId);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Warning: Unable to login as user " + Settings.Username + ": " + e.Message);
                }
            }

            // Interact with the client (acting as a server)

            // Generate verification token
            ClientVerificationToken = new byte[4];
            secureRandom.GetBytes(ClientVerificationToken);
            // Encode public key as an ASN X509 certificate
            var encodedKey = AsnKeyBuilder.PublicKeyToX509(ServerKey);

            if (Settings.AuthenticateClients)
            {
                ClientAuthenticationHash = CreateHash();
            }
            else
            {
                ClientAuthenticationHash = "-";
            }

            ClientEncryptionRequest = new EncryptionKeyRequestPacket
            {
                VerificationToken = ClientVerificationToken,
                ServerId          = ClientAuthenticationHash,
                PublicKey         = encodedKey.GetBytes()
            };
            FinializeClientEncryption(new EncryptionKeyResponsePacket());
        }