Refactor DTOs and simplify PdfDigitalSignatureService
Refactored `PdfSignOptionsDto` and `PdfVisualSignatureOptionsDto`: - Converted both to immutable `record` types with non-nullable properties. - Added XML documentation comments for properties and parameters. Simplified `PdfDigitalSignatureService`: - Updated `SignPdfAsync` to enforce non-nullable `PdfSignOptionsDto`. - Removed redundant null checks and inlined `CreateSignatureBounds`. - Simplified signature appearance and image data logic. - Refactored `TryGetKeySize` to use `bool` with `out` parameter. General improvements: - Enhanced code readability and maintainability. - Reduced nullable references and enforced stricter type safety.
This commit is contained in:
@@ -18,10 +18,8 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
{
|
||||
private static readonly Regex SignatureReasonMetaRegex = new(@"\|\s*SFMETA:v1;doc=(?<doc>[0-9a-fA-F-]{36});sha256=(?<sha>[A-Fa-f0-9]{64})$", RegexOptions.CultureInvariant | RegexOptions.Compiled);
|
||||
|
||||
public async Task SignPdfAsync(Stream inputPdf, Stream outputPdf, PdfSignOptionsDto? optionsModel = null, CancellationToken cancellationToken = default)
|
||||
public async Task SignPdfAsync(Stream inputPdf, Stream outputPdf, PdfSignOptionsDto request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(inputPdf);
|
||||
ArgumentNullException.ThrowIfNull(outputPdf);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var (workingInput, ownsWorkingInput) = await EnsureSeekableInputAsync(inputPdf, cancellationToken);
|
||||
@@ -33,7 +31,7 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
workingInput.Position = 0;
|
||||
|
||||
var pkcs11Options = options.Value;
|
||||
var request = optionsModel ?? new PdfSignOptionsDto();
|
||||
|
||||
var uuid = ResolveUuid(request.UUID);
|
||||
var reasonWithMeta = BuildReasonWithMeta(request.Reason ?? pkcs11Options.DefaultReason, uuid, sourceHashHex);
|
||||
|
||||
@@ -47,9 +45,9 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
Name = $"Sig_{DateTimeOffset.UtcNow:yyyyMMddHHmmss}"
|
||||
};
|
||||
|
||||
var signatureBounds = CreateSignatureBounds(request.VisualSignature);
|
||||
if (signatureBounds is not null)
|
||||
signatureFieldInfo.SignatureBounds = signatureBounds;
|
||||
var left = request.VisualSignature!.Left;
|
||||
var bottom = request.VisualSignature.Bottom;
|
||||
signatureFieldInfo.SignatureBounds = new PdfRectangle(left, bottom, left + request.VisualSignature.Width, bottom + request.VisualSignature.Height);
|
||||
|
||||
var builder = new PdfDeferredSignatureBuilder(signerInfo, signatureFieldInfo)
|
||||
{
|
||||
@@ -64,21 +62,18 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
?? PdfCertificationLevel.NoCertification
|
||||
};
|
||||
|
||||
if(request.VisualSignature is PdfVisualSignatureOptionsDto visualSignature)
|
||||
builder.SetSignatureAppearance(new PdfSignatureAppearance
|
||||
{
|
||||
builder.SetSignatureAppearance(new PdfSignatureAppearance
|
||||
{
|
||||
AppearanceType = PdfSignatureAppearanceType.Name,
|
||||
ShowLabels = visualSignature.ShowLabels,
|
||||
ShowName = true,
|
||||
ShowDate = false,
|
||||
ShowReason = false,
|
||||
ShowLocation = false,
|
||||
ShowDistinguishedName = false
|
||||
});
|
||||
builder.SetImageData(visualSignature.ImageBytes);
|
||||
}
|
||||
|
||||
AppearanceType = PdfSignatureAppearanceType.Name,
|
||||
ShowLabels = request.VisualSignature.ShowLabels,
|
||||
ShowName = true,
|
||||
ShowDate = false,
|
||||
ShowReason = false,
|
||||
ShowLocation = false,
|
||||
ShowDistinguishedName = false
|
||||
});
|
||||
builder.SetImageData(request.VisualSignature.ImageBytes);
|
||||
|
||||
var deferredSigner = signer.SignDeferred(builder);
|
||||
var externalSigner = new Pkcs11ExternalSigner(pkcs11Options);
|
||||
deferredSigner.Sign(outputPdf, externalSigner.BuildSignature(deferredSigner.HashValue, digestCalculator.AlgorithmOid));
|
||||
@@ -92,9 +87,6 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
|
||||
public async Task SignPdfAsync(Stream inputPdf, Stream outputPdf, IReadOnlyList<PdfSignOptionsDto> optionsList, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(inputPdf);
|
||||
ArgumentNullException.ThrowIfNull(outputPdf);
|
||||
ArgumentNullException.ThrowIfNull(optionsList);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (optionsList.Count == 0)
|
||||
@@ -138,7 +130,6 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
|
||||
public async Task<PdfSignatureCheckResultDto> CheckPdfSignatureAsync(Stream inputPdf, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(inputPdf);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var pdfBytes = await ReadAllBytesAsync(inputPdf, cancellationToken);
|
||||
@@ -246,8 +237,6 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
|
||||
public async Task ExtractOriginalPdfAsync(Stream inputPdf, Stream outputPdf, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(inputPdf);
|
||||
ArgumentNullException.ThrowIfNull(outputPdf);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var pdfBytes = await ReadAllBytesAsync(inputPdf, cancellationToken);
|
||||
@@ -338,18 +327,25 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
KeyAlgorithm: certificate.PublicKey.Oid?.FriendlyName ?? certificate.PublicKey.Oid?.Value,
|
||||
SignatureAlgorithm: certificate.SignatureAlgorithm.FriendlyName ?? certificate.SignatureAlgorithm.Value,
|
||||
Pem: ToPem(certificate.RawData),
|
||||
KeySizeBits: TryGetKeySize(certificate));
|
||||
KeySizeBits: TryGetKeySize(certificate, out var keySize) ? keySize : null);
|
||||
}
|
||||
|
||||
private static int? TryGetKeySize(X509Certificate2 certificate)
|
||||
private static bool TryGetKeySize(X509Certificate2 certificate, out int keySize)
|
||||
{
|
||||
keySize = 0;
|
||||
try
|
||||
{
|
||||
return certificate.PublicKey.Key.KeySize;
|
||||
using var rsa = certificate.GetRSAPublicKey();
|
||||
|
||||
if (rsa is null)
|
||||
return false;
|
||||
|
||||
keySize = rsa.KeySize;
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
catch (CryptographicException)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,25 +563,6 @@ public sealed class PdfDigitalSignatureService(IOptions<Pkcs11Options> options)
|
||||
return pageNumber;
|
||||
}
|
||||
|
||||
private static PdfRectangle? CreateSignatureBounds(PdfVisualSignatureOptionsDto? visualOptions)
|
||||
{
|
||||
if (visualOptions is null)
|
||||
return null;
|
||||
|
||||
var left = visualOptions.Left;
|
||||
var bottom = visualOptions.Bottom;
|
||||
var width = visualOptions.Width;
|
||||
var height = visualOptions.Height;
|
||||
|
||||
if (left < 0 || bottom < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(visualOptions), "VisualSignature.Left and VisualSignature.Bottom cannot be negative.");
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(visualOptions), "VisualSignature.Width and VisualSignature.Height must be greater than zero.");
|
||||
|
||||
return new PdfRectangle(left, bottom, left + width, bottom + height);
|
||||
}
|
||||
|
||||
private static string BuildReasonWithMeta(string? businessReason, string uuid, string sourceHashHex)
|
||||
{
|
||||
var trimmedReason = string.IsNullOrWhiteSpace(businessReason) ? null : businessReason.Trim();
|
||||
|
||||
Reference in New Issue
Block a user