using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using Microsoft.IdentityModel.Tokens; using StellaOps.Cryptography; namespace StellaOps.Cryptography.Kms; internal sealed class KmsSigner : ICryptoSigner { private readonly IKmsClient _client; private readonly string _keyId; private readonly string _versionId; private readonly string _algorithm; public KmsSigner(IKmsClient client, KmsSigningRegistration registration) { _client = client; _keyId = registration.KeyId; _versionId = registration.VersionId; _algorithm = registration.Algorithm; } public string KeyId => _keyId; public string AlgorithmId => _algorithm; public async ValueTask SignAsync(ReadOnlyMemory data, CancellationToken cancellationToken = default) { var result = await _client.SignAsync(_keyId, _versionId, data, cancellationToken).ConfigureAwait(false); return result.Signature; } public ValueTask VerifyAsync(ReadOnlyMemory data, ReadOnlyMemory signature, CancellationToken cancellationToken = default) => new(_client.VerifyAsync(_keyId, _versionId, data, signature, cancellationToken)); public JsonWebKey ExportPublicJsonWebKey() { var material = _client.ExportAsync(_keyId, _versionId).GetAwaiter().GetResult(); var jwk = new JsonWebKey { Kid = material.KeyId, Alg = material.Algorithm, Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve, Use = JsonWebKeyUseNames.Sig, Crv = JsonWebKeyECTypes.P256, }; jwk.KeyOps.Add("sign"); jwk.KeyOps.Add("verify"); jwk.X = Base64UrlEncoder.Encode(material.Qx); jwk.Y = Base64UrlEncoder.Encode(material.Qy); return jwk; } }