feat(infrastructure): add PKCS#11 PDF signing infrastructure

This commit is contained in:
2026-10-22 02:26:13 +02:00
parent 3b4134e873
commit d9cd0d60e3
25 changed files with 2560 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
using DocumentOperator.Application.Common.Configurations;
using DevExpress.Office.DigitalSignatures;
using DevExpress.Pdf;
namespace DocumentService.Infrastructure.Crypt.Services;
internal sealed class Pkcs11ExternalSigner(Pkcs11Options options) : Pkcs7SignerBase
{
private readonly Pkcs11PdfSigningRsa rsa = new(options);
private readonly DigestCalculator digestCalculator = new(HashAlgorithmType.SHA256);
private readonly IReadOnlyList<byte[]> certificates = [ReadCertificateBytesWithFallback(options)];
protected override IDigestCalculator DigestCalculator => digestCalculator;
protected override string SigningAlgorithmOID => "1.2.840.113549.1.1.1";
protected override IEnumerable<byte[]> GetCertificates() => certificates;
protected override byte[] SignDigest(byte[] digest)
{
return rsa.SignHash(digest, System.Security.Cryptography.HashAlgorithmName.SHA256, System.Security.Cryptography.RSASignaturePadding.Pkcs1);
}
private static byte[] ReadCertificateBytesWithFallback(Pkcs11Options options)
{
try
{
return Pkcs11SessionRunner.Run(options, session =>
{
var attrs = new List<Net.Pkcs11Interop.HighLevelAPI.IObjectAttribute>
{
session.Factories.ObjectAttributeFactory.Create(Net.Pkcs11Interop.Common.CKA.CKA_CLASS, Net.Pkcs11Interop.Common.CKO.CKO_CERTIFICATE),
session.Factories.ObjectAttributeFactory.Create(Net.Pkcs11Interop.Common.CKA.CKA_LABEL, options.CertificateLabel)
};
var handles = session.FindAllObjects(attrs);
if (handles.Count == 0)
throw new InvalidOperationException($"Certificate '{options.CertificateLabel}' not found in token.");
var values = session.GetAttributeValue(handles[0], new List<Net.Pkcs11Interop.Common.CKA> { Net.Pkcs11Interop.Common.CKA.CKA_VALUE });
return values[0].GetValueAsByteArray();
});
}
catch when (Pkcs11ToolBridge.IsAvailable(options))
{
return Pkcs11ToolBridge.ReadCertificateBytes(options);
}
}
}