Fix bug: Yggdrasil client can't send message upper 22w17a

When try to send message in yggdrasil-auth server with `enforce-secure-profile=true`
and `online-mode=true` enabled, will fail with message in red:
Chat disabled due to missing profile public key. Please try reconnecting.
So yggdrasil-auth-client also has to encrypt chat messages like Microsoft-auth-client
to send out messages.
This commit is contained in:
oldkingOK 2024-01-13 03:00:02 +08:00
parent 22cf7a046b
commit 2c8b15b02e
2 changed files with 46 additions and 13 deletions

View file

@ -5,6 +5,7 @@ using System.Text;
using MinecraftClient.Protocol.Handlers;
using MinecraftClient.Protocol.Message;
using static MinecraftClient.Protocol.Message.LastSeenMessageList;
using Newtonsoft.Json.Linq;
namespace MinecraftClient.Protocol.ProfileKey
{
@ -14,27 +15,34 @@ namespace MinecraftClient.Protocol.ProfileKey
private static readonly string certificates = "https://api.minecraftservices.com/player/certificates";
public static PlayerKeyPair? GetNewProfileKeys(string accessToken)
public static PlayerKeyPair? GetNewProfileKeys(string accessToken, bool isYggdrasil)
{
ProxiedWebRequest.Response? response = null;
try
{
var request = new ProxiedWebRequest(certificates)
{
Accept = "application/json"
};
request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken));
if (!isYggdrasil) {
var request = new ProxiedWebRequest(certificates)
{
Accept = "application/json"
};
request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken));
response = request.Post("application/json", "");
response = request.Post("application/json", "");
if (Settings.Config.Logging.DebugMessages)
{
ConsoleIO.WriteLine(response.Body.ToString());
if (Settings.Config.Logging.DebugMessages)
{
ConsoleIO.WriteLine(response.Body.ToString());
}
}
string jsonString = response.Body;
// see https://github.com/yushijinhun/authlib-injector/blob/da910956eaa30d2f6c2c457222d188aeb53b0d1f/src/main/java/moe/yushi/authlibinjector/httpd/ProfileKeyFilter.java#L49
// POST to "https://api.minecraftservices.com/player/certificates" with authlib-injector will get a dummy response
string jsonString = isYggdrasil ? MakeDummyResponse() : response!.Body;
Json.JSONData json = Json.ParseJson(jsonString);
Console.WriteLine("Got public key:" + json.Properties["keyPair"].Properties["publicKey"].StringValue);
Console.WriteLine("Got private key:" + json.Properties["keyPair"].Properties["privateKey"].StringValue);
// Error here
PublicKey publicKey = new(pemKey: json.Properties["keyPair"].Properties["publicKey"].StringValue,
sig: json.Properties["publicKeySignature"].StringValue,
sigV2: json.Properties["publicKeySignatureV2"].StringValue);
@ -230,5 +238,30 @@ namespace MinecraftClient.Protocol.ProfileKey
sb.Append(src, start, src.Length - start);
return sb.ToString();
}
public static string MakeDummyResponse()
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048);
var mimePublicKey = Convert.ToBase64String(rsa.ExportSubjectPublicKeyInfo());
var mimePrivateKey = Convert.ToBase64String(rsa.ExportPkcs8PrivateKey());
string publicKeyPEM = $"-----BEGIN RSA PUBLIC KEY-----\n{mimePublicKey}\n-----END RSA PUBLIC KEY-----\n";
string privateKeyPEM = $"-----BEGIN RSA PRIVATE KEY-----\n{mimePrivateKey}\n-----END RSA PRIVATE KEY-----\n";
DateTime now = DateTime.UtcNow;
DateTime expiresAt = now.AddHours(48);
DateTime refreshedAfter = now.AddHours(36);
JObject response = new JObject();
JObject keyPairObj = new JObject
{
{ "privateKey", privateKeyPEM },
{ "publicKey", publicKeyPEM }
};
response.Add("keyPair", keyPairObj);
response.Add("publicKeySignature", "AA==");
response.Add("publicKeySignatureV2", "AA==");
string format = "yyyy-MM-ddTHH:mm:ss.ffffffZ";
response.Add("expiresAt", expiresAt.ToString(format));
response.Add("refreshedAfter", refreshedAfter.ToString(format));
return response.ToString();
}
}
}