/// <summary>
        /// Login to Minecraft.net and store credentials
        /// </summary>
        public void Login() {
            if (VerifyNames) {
                var loginHandler = new MinecraftNetInteraction();
                var credentials = loginHandler.Login(ClientName, ClientPassword);

                if (credentials[0] == "") {  // -- Fall back to no auth.
                    RaiseError(this, "Failed to login to Minecraft.net! (Incorrect username or password)");

                    VerifyNames = false;
                } else {
                    RaiseInfo(this, "Logged in to Minecraft.net successfully.");

                    RaiseDebug(this, string.Format("Token: {0}\nProfile: {1}", credentials[0], credentials[1]));

                    AccessToken = credentials[0];
                    SelectedProfile = credentials[1];
                    ClientToken = credentials[2];
                    ClientName = credentials[3];
                }
            } else {
                AccessToken = "None";
                SelectedProfile = "None";
            }

        }
        /// <summary>
        /// Uses a client's stored credentials to verify with Minecraft.net
        /// </summary>
        public bool VerifySession() {
            if (AccessToken == null || ClientToken == null) {
                RaiseError(this, "Credentials are not set!");
                return false;
            }

            var sessionVerifier = new MinecraftNetInteraction();
            var response = sessionVerifier.SessionRefresh(AccessToken, ClientToken);

            if (response[0] == "") {
                RaiseError(this, "Unable to Verify Session!");
                return false;
            }

            RaiseInfo(this, "Credentials verified and refreshed!");

            AccessToken = response[0];
            ClientToken = response[1];
            SelectedProfile = "Potato";

            return true;
        }
        public void HandleEncryptionRequest(MinecraftClient client, IPacket packet) {
            var er = (CbEncryptionRequest)packet;
            var sharedKey = new byte[16];

            var random = RandomNumberGenerator.Create(); // -- Generate a random shared key.
            random.GetBytes(sharedKey);

            if (er.ServerId == "" && client.VerifyNames) {
                // -- Verify with Minecraft.net.
                // -- At this point, the server requires a hash containing the server id,
                // -- shared key, and original public key. So we make this, and then pass to Minecraft.net

                var hashList = new List<byte>();
                hashList.AddRange(Encoding.ASCII.GetBytes(er.ServerId));
                hashList.AddRange(sharedKey);
                hashList.AddRange(er.PublicKey);

                var hashData = hashList.ToArray();
                var hash = JavaHexDigest(hashData);

                var verify = new MinecraftNetInteraction();

                if (!verify.VerifyName(client.ClientName, client.AccessToken, client.SelectedProfile, hash)) {
                    client.RaiseLoginFailure(this, "Failed to verify name with Minecraft session server.");
                    client.Disconnect();
                    return;
                }
            } else
                client.RaiseInfo(this, "Name verification disabled, skipping authentication.");

            // -- AsnKeyParser is a part of the cryptography.dll, which is simply a compiled version
            // -- of SMProxy's Cryptography.cs, with the server side parts stripped out.
            // -- You pass it the key data and ask it to parse, and it will 
            // -- Extract the server's public key, then parse that into RSA for us.

            var keyParser = new AsnKeyParser(er.PublicKey);
            var dekey = keyParser.ParseRSAPublicKey();

            // -- Now we create an encrypter, and encrypt the token sent to us by the server
            // -- as well as our newly made shared key (Which can then only be decrypted with the server's private key)
            // -- and we send it to the server.

            var cryptoService = new RSACryptoServiceProvider(); // -- RSA Encryption class
            cryptoService.ImportParameters(dekey); // -- Import the Server's public key to use as the RSA encryption key.

            var encryptedSecret = cryptoService.Encrypt(sharedKey, false); // -- Encrypt the Secret key and verification token.
            var encryptedVerify = cryptoService.Encrypt(er.VerifyToken, false);

            client.Nh.WSock.InitEncryption(sharedKey); // -- Give the shared secret key to the socket

            var response = new SbEncryptionResponse
            {
                SharedLength = (short) encryptedSecret.Length,
                SharedSecret = encryptedSecret,
                VerifyLength = (short) encryptedVerify.Length,
                VerifyToken = encryptedVerify
            }; // -- Respond to the server

            response.Write(client.Nh.WSock);

            client.Nh.WSock.EncEnabled = true;
            client.Nh.RaiseSocketInfo(this, "Encryption Enabled.");
        }
        /// <summary>
        /// Uses a client's stored credentials to verify with Minecraft.net
        /// </summary>
        /// <param name="accessToken">Stored Access Token</param>
        /// <param name="clientToken">Stored Client Token</param>
        public bool VerifySession(string accessToken, string clientToken) {
            AccessToken = accessToken;
            ClientToken = clientToken;

            var sessionVerifier = new MinecraftNetInteraction();
            var response = sessionVerifier.SessionRefresh(AccessToken, ClientToken);

            if (response[0] == "") {
                RaiseError(this, "Unable to Verify Session!");
                return false;
            }

            RaiseInfo(this, "Credentials verified and refreshed!");

            AccessToken = response[0];
            ClientToken = response[1];

            return true;
        }