using System.Security.Cryptography; using System.Text; using Microsoft.IdentityModel.Tokens; namespace AuthHex.Utility; public class RsaKeyProvider { private readonly RSA _rsa; public RsaKeyProvider(string privateKeyXml) { _rsa = RSA.Create(); _rsa.FromXmlString(privateKeyXml); } public RsaSecurityKey GetPrivateKey() { var key = new RsaSecurityKey(_rsa); var publicParameters = _rsa.ExportParameters(false); key.KeyId = ComputeKeyId(publicParameters); return key; } public RsaSecurityKey GetPublicKey() { var publicKeyRsa = RSA.Create(); var publicParameters = _rsa.ExportParameters(false); publicKeyRsa.ImportParameters(publicParameters); var key = new RsaSecurityKey(publicKeyRsa); key.KeyId = ComputeKeyId(publicParameters); return key; } private static string ComputeKeyId(RSAParameters publicParameters) { var modulus = publicParameters.Modulus ?? Array.Empty(); var exponent = publicParameters.Exponent ?? Array.Empty(); var payload = $"{Convert.ToBase64String(modulus)}.{Convert.ToBase64String(exponent)}"; var hash = SHA256.HashData(Encoding.UTF8.GetBytes(payload)); return Base64UrlEncoder.Encode(hash); } public static (string privateKey, string publicKey) GenerateKeys() { using var rsa = RSA.Create(2048); var privateKey = rsa.ToXmlString(true); // includes private key var publicKey = rsa.ToXmlString(false); // public key only return (privateKey, publicKey); } }