50 lines
2.1 KiB
C#
50 lines
2.1 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|