using EnvelopeGenerator.Application.Common.Configurations; using Net.Pkcs11Interop.Common; using Net.Pkcs11Interop.HighLevelAPI; using System.Security.Cryptography; namespace EnvelopeGenerator.Infrastructure.Crypt.Services; internal sealed class Pkcs11PdfSigningRsa(Pkcs11Options options) : RSA { public override int KeySize { get => KeySizeValue; set => KeySizeValue = value; } public override KeySizes[] LegalKeySizes => [new(1024, 8192, 8)]; public override string? KeyExchangeAlgorithm => "RSA"; public override string SignatureAlgorithm => "RSA"; public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) { if (padding != RSASignaturePadding.Pkcs1) throw new NotSupportedException("Only RSA PKCS#1 v1.5 padding is supported."); byte[] digestInfo = Pkcs11DigestInfoBuilder.Build(hash, hashAlgorithm); try { return Pkcs11SessionRunner.Run(options, session => { var attrs = new List { session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY), session.Factories.ObjectAttributeFactory.Create(CKA.CKA_LABEL, options.PrivateKeyLabel) }; var handles = session.FindAllObjects(attrs); if (handles.Count == 0) throw new InvalidOperationException($"Private key '{options.PrivateKeyLabel}' not found in token."); var mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS); return session.Sign(mechanism, handles[0], digestInfo); }); } catch when (Pkcs11ToolBridge.IsAvailable(options)) { return Pkcs11ToolBridge.SignDigestInfo(options, digestInfo); } } public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) => throw new NotSupportedException(); public override byte[] Decrypt(byte[] data, RSAEncryptionPadding padding) => throw new NotSupportedException(); public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding) => throw new NotSupportedException(); public override RSAParameters ExportParameters(bool includePrivateParameters) => throw new NotSupportedException(); public override void ImportParameters(RSAParameters parameters) => throw new NotSupportedException(); }