Rewrote AES stream & Perform "SessionCheck" in advance

This commit is contained in:
BruceChen 2022-08-27 23:01:28 +08:00
parent a3971f9097
commit 13d1a9856a
28 changed files with 306 additions and 2807 deletions

View file

@ -10,6 +10,7 @@ using System.Security.Cryptography;
using MinecraftClient.Mapping;
using MinecraftClient.Inventory;
using MinecraftClient.Protocol.Keys;
using MinecraftClient.Protocol.Session;
namespace MinecraftClient.Protocol.Handlers
{
@ -439,7 +440,7 @@ namespace MinecraftClient.Protocol.Handlers
else c.Client.Send(buffer);
}
private bool Handshake(string uuid, string username, string sessionID, string host, int port)
private bool Handshake(string uuid, string username, string sessionID, string host, int port, SessionToken session)
{
//array
byte[] data = new byte[10 + (username.Length + host.Length) * 2];
@ -493,7 +494,7 @@ namespace MinecraftClient.Protocol.Handlers
else if (Settings.DebugMessages)
ConsoleIO.WriteLineFormatted(Translations.Get("mcc.handshake", serverID));
return StartEncryption(uuid, username, sessionID, token, serverID, PublicServerkey);
return StartEncryption(uuid, username, sessionID, token, serverID, PublicServerkey, session);
}
else
{
@ -502,10 +503,10 @@ namespace MinecraftClient.Protocol.Handlers
}
}
private bool StartEncryption(string uuid, string username, string sessionID, byte[] token, string serverIDhash, byte[] serverKey)
private bool StartEncryption(string uuid, string username, string sessionID, byte[] token, string serverIDhash, byte[] serverPublicKey, SessionToken session)
{
System.Security.Cryptography.RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverKey);
byte[] secretKey = CryptoHandler.GenerateAESPrivateKey();
RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey);
byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey();
if (Settings.DebugMessages)
Translations.WriteLineFormatted("debug.crypto");
@ -513,13 +514,34 @@ namespace MinecraftClient.Protocol.Handlers
if (serverIDhash != "-")
{
Translations.WriteLine("mcc.session");
if (!ProtocolHandler.SessionCheck(uuid, sessionID, CryptoHandler.getServerHash(serverIDhash, serverKey, secretKey)))
string serverHash = CryptoHandler.getServerHash(serverIDhash, serverPublicKey, secretKey);
bool needCheckSession = true;
if (session.ServerPublicKey != null && session.SessionPreCheckTask != null
&& serverIDhash == session.ServerIDhash && Enumerable.SequenceEqual(serverPublicKey, session.ServerPublicKey))
{
handler.OnConnectionLost(ChatBot.DisconnectReason.LoginRejected, Translations.Get("mcc.session_fail"));
return false;
session.SessionPreCheckTask.Wait();
if (session.SessionPreCheckTask.Result) // PreCheck Successed
needCheckSession = false;
}
if (needCheckSession)
{
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash))
{
session.ServerIDhash = serverIDhash;
session.ServerPublicKey = serverPublicKey;
SessionCache.Store(Settings.Login.ToLower(), session);
}
else
{
handler.OnConnectionLost(ChatBot.DisconnectReason.LoginRejected, Translations.Get("mcc.session_fail"));
return false;
}
}
}
//Encrypt the data
byte[] key_enc = RSAService.Encrypt(secretKey, false);
byte[] token_enc = RSAService.Encrypt(token, false);
@ -557,9 +579,9 @@ namespace MinecraftClient.Protocol.Handlers
}
}
public bool Login(PlayerKeyPair playerKeyPair)
public bool Login(PlayerKeyPair? playerKeyPair, SessionToken session)
{
if (Handshake(handler.GetUserUUID(), handler.GetUsername(), handler.GetSessionID(), handler.GetServerHost(), handler.GetServerPort()))
if (Handshake(handler.GetUserUUID(), handler.GetUsername(), handler.GetSessionID(), handler.GetServerHost(), handler.GetServerPort(), session))
{
Send(new byte[] { 0xCD, 0 });
try