/// <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; }