using System.Security.Cryptography; namespace GB5Shared.DigitalSignature { // Produces a DETACHED cryptographic signature over a finished document's bytes — not an // embedded PDF/PAdES signature. iText7's PdfSigner (the embedded-signature route) requires // itext7.bouncy-castle-adapter, which pulls in BouncyCastle.Cryptography — a hard type // conflict with this codebase's existing Portable.BouncyCastle dependency (confirmed: 21 // compile errors across GB5Shared on first attempt). This detached approach needs no new // dependency: SHA256(document) is signed via IDigitalSignatureService.SignHashAsync (the same // cert-store-by-thumbprint mechanism GenerateSignature.cs already used), and the hash + // signature + thumbprint are stored alongside the document for independent verification. // Trade-off: a generic PDF viewer won't show "Signed and valid" the way an embedded PAdES // signature would — only GB5's own verification path can check it. public static class DetachedDocumentSigner { public static async Task SignAsync(byte[] documentBytes, string thumbprint, IDigitalSignatureService signingService, CancellationToken ct) { byte[] hash = SHA256.HashData(documentBytes); byte[] signature = await signingService.SignHashAsync(thumbprint, hash, ct).ConfigureAwait(false); return new DetachedSignatureResult { Sha256Hash = Convert.ToHexString(hash), SignatureBase64 = Convert.ToBase64String(signature) }; } } public sealed class DetachedSignatureResult { public string Sha256Hash { get; set; } = string.Empty; public string SignatureBase64 { get; set; } = string.Empty; } }