using System; using System.Security.Cryptography; using MinecraftClient.Protocol.Message; namespace MinecraftClient.Protocol.ProfileKey { public class PublicKey { public byte[] Key { get; set; } public byte[]? Signature { get; set; } public byte[]? SignatureV2 { get; set; } private readonly RSA rsa; public PublicKey(string pemKey, string? sig = null, string? sigV2 = null) { Key = KeyUtils.DecodePemKey(pemKey, "-----BEGIN RSA PUBLIC KEY-----", "-----END RSA PUBLIC KEY-----"); rsa = RSA.Create(); rsa.ImportSubjectPublicKeyInfo(Key, out _); if (!string.IsNullOrEmpty(sig)) Signature = Convert.FromBase64String(sig); if (!string.IsNullOrEmpty(sigV2)) SignatureV2 = Convert.FromBase64String(sigV2!); if (SignatureV2 == null || SignatureV2.Length == 0) SignatureV2 = Signature; if (Signature == null || Signature.Length == 0) Signature = SignatureV2; } public PublicKey(byte[] key, byte[] signature) { Key = key; rsa = RSA.Create(); rsa.ImportSubjectPublicKeyInfo(Key, out _); Signature = signature; } public bool VerifyData(byte[] data, byte[] signature) { return rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); } /// /// Verify message - 1.19 /// /// Message content /// Sender uuid /// Timestamp /// Salt /// Message signature /// Is this message vaild public bool VerifyMessage(string message, Guid uuid, DateTimeOffset timestamp, ref byte[] salt, ref byte[] signature) { byte[] data = KeyUtils.GetSignatureData(message, uuid, timestamp, ref salt); return VerifyData(data, signature); } /// /// Verify message - 1.19.1 and 1.19.2 /// /// Message content /// Sender uuid /// Timestamp /// Salt /// Message signature /// Preceding message signature /// LastSeenMessages /// Is this message vaild public bool VerifyMessage(string message, Guid uuid, DateTimeOffset timestamp, ref byte[] salt, ref byte[] signature, ref byte[]? precedingSignature, LastSeenMessageList lastSeenMessages) { byte[] bodySignData = KeyUtils.GetSignatureData(message, timestamp, ref salt, lastSeenMessages); byte[] bodyDigest = KeyUtils.ComputeHash(bodySignData); byte[] msgSignData = KeyUtils.GetSignatureData(precedingSignature, uuid, bodyDigest); return VerifyData(msgSignData, signature); } /// /// Verify message head - 1.19.1 and 1.19.2 /// /// Message body hash /// Message signature /// Is this message header vaild public bool VerifyHeader(Guid uuid, ref byte[] bodyDigest, ref byte[] signature, ref byte[]? precedingSignature) { byte[] msgSignData = KeyUtils.GetSignatureData(precedingSignature, uuid, bodyDigest); return VerifyData(msgSignData, signature); } } }