using Microsoft.IdentityModel.Tokens; using Org.BouncyCastle.Pqc.Crypto.Falcon; using StellaOps.Cryptography; using System.Threading; using System.Threading.Tasks; namespace StellaOps.Cryptography.Plugin.PqSoft; internal sealed class FalconSignerWrapper : ICryptoSigner { private readonly string _keyId; private readonly FalconPrivateKeyParameters _privateKey; private readonly FalconPublicKeyParameters _publicKey; public FalconSignerWrapper(string keyId, FalconPrivateKeyParameters privateKey, FalconPublicKeyParameters publicKey) { _keyId = keyId; _privateKey = privateKey; _publicKey = publicKey; } public string KeyId => _keyId; public string AlgorithmId => SignatureAlgorithms.Falcon512; public ValueTask SignAsync(ReadOnlyMemory data, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var signer = new FalconSigner(); signer.Init(true, _privateKey); return ValueTask.FromResult(signer.GenerateSignature(data.ToArray())); } public ValueTask VerifyAsync(ReadOnlyMemory data, ReadOnlyMemory signature, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); var verifier = new FalconSigner(); verifier.Init(false, _publicKey); var ok = verifier.VerifySignature(data.ToArray(), signature.ToArray()); return ValueTask.FromResult(ok); } public JsonWebKey ExportPublicJsonWebKey() { var jwk = new JsonWebKey { Kid = _keyId, Alg = AlgorithmId, Kty = JsonWebAlgorithmsKeyTypes.Octet, Use = JsonWebKeyUseNames.Sig, Crv = "Falcon512" }; jwk.KeyOps.Add("sign"); jwk.KeyOps.Add("verify"); jwk.X = Base64UrlEncoder.Encode(_publicKey.GetEncoded()); return jwk; } }