HotPDF är ett nativt VCL PDF-bibliotek för Delphi- och C++Builder-program som behöver direkt PDF-skapande och redigering, formulär, annoteringar, kryptering, digitala signaturer, Unicode-teckensnitt, standardmedveten utdata och preflight-rapporter utan extern PDF-runtime.
Den här artikeln är skriven för Delphi team som lägger till certificate-based approval, invoice signing, or long-term validation evidence. Den behandlar digital signatures and PAdES-ready signing som produktionsnära dokumentteknik, inte som ett isolerat komponentanrop.
Den praktiska risken är att a PDF may contain a visible signature box while the byte range, certificate chain, timestamp, revocation data, or later incremental update invalidates trust. Därför behöver flödet ett skrivet kontrakt, observerbar diagnostik och realistiska regressionsfiler.
Arkitekturbeslut
Design signing as a revision-controlled workflow. certificate source, private-key boundary, and operator approval process / timestamp authority, revocation source, and long-term validation profile
- certificate source, private-key boundary, and operator approval process
- timestamp authority, revocation source, and long-term validation profile
- visible signature appearance, signer reason, contact, and location fields
- whether later annotations, forms, or metadata updates are allowed after signing
Implementeringsflöde
Prepare evidence before reserving the signature field. Ordningen nedan gör arbetsflödet granskbart för Delphi- och C++Builder-team.
- freeze the document content and preflight it before signature reservation
- load certificate material from the approved key store or signing service
- reserve the signature field and byte range with enough space for the final value
- apply timestamp and revocation data according to the selected PAdES profile
- verify the final file in at least one independent validator before release
Valideringsbevis
Signature evidence worth keeping. Behåll dessa fält tillsammans med utdata eller supportunderlaget.
- signer certificate fingerprint, chain status, timestamp result, and revocation source
- signature byte range, digest algorithm, PAdES profile, and validation summary
- document hash before signing and final hash after the signed revision is saved
- policy decision for any warning that did not block the signature
PAdES is a lifecycle, not only a signature
PAdES-ready output needs deterministic document bytes, a verified certificate context, timestamp policy, revocation evidence, and a save strategy that does not alter signed byte ranges after the signature is applied.
Profile ownership and versioning
A named, versioned profile is easier to review than options scattered across forms, scripts, and batch parameters. It also makes support reports readable when customers use older templates or policies.
- certificate source, private-key boundary, and operator approval process
- timestamp authority, revocation source, and long-term validation profile
- visible signature appearance, signer reason, contact, and location fields
- whether later annotations, forms, or metadata updates are allowed after signing
- signer certificate fingerprint, chain status, timestamp result, and revocation source
- signature byte range, digest algorithm, PAdES profile, and validation summary
Tekniska granskningsnoteringar för digital signatures and PAdES-ready signing
Använd dessa granskningsnoteringar för att säkerställa att funktionen har passerat demo-nivån och kan försvaras under leverans, support och kundeskalering.
- Beslut: certificate source, private-key boundary, and operator approval process. Implementeringspresspunkt: load certificate material from the approved key store or signing service. Acceptansbevis: document hash before signing and final hash after the signed revision is saved. Regressionsutlösare: timestamp and revocation services need timeout and retry policies
- Beslut: timestamp authority, revocation source, and long-term validation profile. Implementeringspresspunkt: reserve the signature field and byte range with enough space for the final value. Acceptansbevis: policy decision for any warning that did not block the signature. Regressionsutlösare: editing metadata or form values after signing can invalidate the signed revision
- Beslut: visible signature appearance, signer reason, contact, and location fields. Implementeringspresspunkt: apply timestamp and revocation data according to the selected PAdES profile. Acceptansbevis: signer certificate fingerprint, chain status, timestamp result, and revocation source. Regressionsutlösare: certificate chain checks can pass on a developer machine but fail offline
- Beslut: whether later annotations, forms, or metadata updates are allowed after signing. Implementeringspresspunkt: verify the final file in at least one independent validator before release. Acceptansbevis: signature byte range, digest algorithm, PAdES profile, and validation summary. Regressionsutlösare: visible appearance text should not be treated as cryptographic evidence
- Beslut: certificate source, private-key boundary, and operator approval process. Implementeringspresspunkt: freeze the document content and preflight it before signature reservation. Acceptansbevis: document hash before signing and final hash after the signed revision is saved. Regressionsutlösare: timestamp and revocation services need timeout and retry policies
Gränsfall
- editing metadata or form values after signing can invalidate the signed revision
- certificate chain checks can pass on a developer machine but fail offline
- visible appearance text should not be treated as cryptographic evidence
- timestamp and revocation services need timeout and retry policies
Delphi / C++Builder notes
HotPDF Component should sit behind a small service boundary that receives files, streams, profiles, and credentials, then returns output paths, warnings, metrics, and validation status. Important terms include PAdES, digital signature, byte range, timestamp, DSS, revocation.
Delphi-kodexempel
Följande Delphi-skiss visar en praktisk servicegräns för detta ämne. Håll policykontroller, loggning och validering utanför det smala produktanropet så att arbetsflödet går att testa.
procedure SignApprovedPdf(const InputFile, OutputFile: string; const Policy: TSignaturePolicy);
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
LoadUnsignedPackage(Pdf, InputFile);
CheckSigningPolicy(Policy);
AttachPadesEvidence(Pdf, Policy.Certificate, Policy.TimestampServer);
SaveSignedPackage(Pdf, OutputFile);
ValidateSignatureChain(OutputFile, Policy.TrustAnchors);
finally
Pdf.Free;
end;
end;
Produktionschecklista
- Kör arbetsflödet på en tom fil, en normal kundfil och en värstafallfil
- Öppna den genererade PDF-filen med rätt visare, validator, skrivare eller nedströmsapplikation
- Logga produktversion, profilversion, inmatningshash, utdatasökväg, förfluten tid och antal varningar
- Håll lösenord, certifikat, tillfälliga filer och kunddata under tydliga lagringsregler
- Lägg till regressionsdokument när en kundfil avslöjar ett nytt gränsfall
Produktdokumentation
Fler kodexempel
var
Doc: THotPDF;
Fs: TFileStream;
PdfBytes, HashInput, SigHex: AnsiString;
R1Start, R1Len, R2Start, R2Len, CStart, CLen: Integer;
begin
// 1. Write the document with a reserved /Contents hole
Doc := THotPDF.Create(nil);
try
Doc.FileName := 'placeholder.pdf';
Doc.BeginDoc;
Doc.CurrentPage.AddSignedSignatureField('Sig1',
Rect(50, 100, 350, 150), 8192, 'adbe.pkcs7.detached',
'Contract approval', 'Boston, MA', 'legal@example.com');
Doc.EndDoc;
finally
Doc.Free;
end;
// 2. Load the saved bytes; the returned offsets are 0-based
Fs := TFileStream.Create('placeholder.pdf', fmOpenRead);
try
SetLength(PdfBytes, Fs.Size);
Fs.ReadBuffer(PdfBytes[1], Fs.Size);
finally
Fs.Free;
end;
THotPDF.PreparePDFForSigning(PdfBytes, R1Start, R1Len, R2Start, R2Len,
CStart, CLen);
// 3. Hash both spans and sign externally (HSM, token, service)
HashInput := Copy(PdfBytes, R1Start + 1, R1Len) +
Copy(PdfBytes, R2Start + 1, R2Len);
SigHex := SignWithHsm(HashInput); // your integration: returns CMS as hex
// 4. Splice the signature into the reserved hole
THotPDF.InsertSignatureHex(PdfBytes, SigHex);
Fs := TFileStream.Create('signed.pdf', fmCreate);
try
Fs.WriteBuffer(PdfBytes[1], Length(PdfBytes));
finally
Fs.Free;
end;
end;// PAdES baseline signature field (ETSI EN 319 142-1)
Pdf.CurrentPage.AddPAdESSignatureField(
'ApprovalSig', Rect(50, 100, 350, 150), 'B-B',
'Contract approval', 'Boston, MA', 'legal@example.com');
// Document timestamp: larger reservation for the TSA token and chain
Pdf.CurrentPage.AddDocumentTimestampSignature('ArchiveTS', 16384);