losLab PDF Library zapewnia zespołom Delphi i C++Builder silnik PDF z dostępnym kodem źródłowym dla przepływów desktopowych, serwerowych, DLL, ActiveX i Dylib, z wbudowanymi kontrolami PDF/A i PDF/UA, podpisami PAdES oraz wyborem renderera bez wysyłania dokumentów do zewnętrznej usługi PDF
Ten artykuł jest przeznaczony dla teams that need to create, inspect, and validate signed PDF workflows inside Delphi applications. Traktuje PAdES signing and validation jako produkcyjną inżynierię dokumentów, a nie pojedyncze wywołanie komponentu
Praktyczne ryzyko polega na tym, że signature creation and signature validation are often implemented separately, causing mismatched trust decisions when timestamps, revocation data, or incremental updates change. Dlatego przepływ wymaga spisanego kontraktu, obserwowalnej diagnostyki i realistycznych plików regresyjnych
Decyzje architektoniczne
Use one trust policy for signing and validation. accepted certificate stores, chain policy, timestamp source, and revocation source / PAdES profile, long-term validation requirements, and archive retention period
- accepted certificate stores, chain policy, timestamp source, and revocation source
- PAdES profile, long-term validation requirements, and archive retention period
- whether warnings create a block, manual review, or documented waiver
- how later document changes are restricted after the trusted revision
Przebieg implementacji
Validate the final signed revision, not the draft. Poniższa kolejność zachowuje czytelność przepływu pracy dla zespołów Delphi i C++Builder
- prepare the document and collect validation prerequisites before signing
- apply the signature, timestamp, and revocation evidence according to policy
- validate the final signed file and classify every warning
- store trust evidence with the business record rather than only inside the PDF
- revalidate representative files when trust anchors or policy change
Dowody walidacji
Trust evidence for signed documents. Zachowaj te pola wraz z wynikiem lub rekordem wsparcia
- signature status, byte range, digest algorithm, signer certificate, and chain result
- timestamp token status, revocation source, DSS/VRI presence, and validation time
- policy version, warning classification, and waiver decision
- final signed file hash and validator result
Long-term validation needs supporting data
PAdES workflows need certificate-chain checks, timestamps, revocation data, DSS/VRI information, byte-range validation, and policy decisions for warnings. The final file must be validated after all signing bytes are written
Zachowanie widoczne dla klienta
Użytkownicy nie widzą wewnętrznej kolejności wywołań. Widzą, czy plik się otwiera, przechodzi walidację, drukuje się, edytuje, importuje lub zostaje odrzucony. The workflow should translate PAdES signing and validation results into states users can act on
- prepare the document and collect validation prerequisites before signing
- apply the signature, timestamp, and revocation evidence according to policy
- validate the final signed file and classify every warning
- a signature can be cryptographically intact but untrusted by current policy
- revocation services may be unavailable when the document is signed
Notatki przeglądu inżynierskiego dla PAdES signing and validation
Użyj tych notatek przeglądu, aby upewnić się, że funkcja wyszła poza demonstrację i da się ją obronić podczas wydania, wsparcia i eskalacji klienta
- Decyzja: accepted certificate stores, chain policy, timestamp source, and revocation source. Punkt nacisku implementacji: apply the signature, timestamp, and revocation evidence according to policy. Dowody akceptacji: policy version, warning classification, and waiver decision. Wyzwalacz regresji: clock differences can make timestamp and certificate validity hard to explain
- Decyzja: PAdES profile, long-term validation requirements, and archive retention period. Punkt nacisku implementacji: validate the final signed file and classify every warning. Dowody akceptacji: final signed file hash and validator result. Wyzwalacz regresji: a signature can be cryptographically intact but untrusted by current policy
- Decyzja: whether warnings create a block, manual review, or documented waiver. Punkt nacisku implementacji: store trust evidence with the business record rather than only inside the PDF. Dowody akceptacji: signature status, byte range, digest algorithm, signer certificate, and chain result. Wyzwalacz regresji: revocation services may be unavailable when the document is signed
Przypadki brzegowe
- a signature can be cryptographically intact but untrusted by current policy
- revocation services may be unavailable when the document is signed
- incremental updates after signing need a clear allowed-change policy
- clock differences can make timestamp and certificate validity hard to explain
Delphi / C++Builder notes
PDFlibPas 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, signature validation, timestamp, revocation, DSS, byte range
Przykład kodu Delphi
Poniższy szkic Delphi pokazuje praktyczną granicę usługi dla tego tematu. Kontrole zasad, logowanie i walidację trzymaj poza wąskim blokiem wywołań produktu, aby przepływ pozostał testowalny
procedure ValidatePadesPackage(const InputFile: string; const TrustPolicy: TTrustPolicy);
var
Pdf: TPDFlib;
ProcessId: Integer;
begin
Pdf := TPDFlib.Create;
try
ProcessId := Pdf.NewSignProcessFromFile(InputFile, '');
CheckByteRange(Pdf, ProcessId);
ValidateCertificatePath(Pdf, ProcessId, TrustPolicy);
Pdf.ReleaseSignProcess(ProcessId);
finally
Pdf.Free;
end;
end;
Lista produkcyjna
- Uruchom przepływ pracy na pustym pliku, zwykłym pliku klienta i pliku z najgorszego scenariusza
- Otwórz wygenerowany plik PDF w docelowej przeglądarce, walidatorze, drukarce lub aplikacji nadrzędnej
- Zaloguj wersję produktu, wersję profilu, hash wejścia, ścieżkę wyjścia, czas wykonania i liczbę ostrzeżeń
- Przechowuj hasła, certyfikaty, pliki tymczasowe i dane klienta zgodnie z jednoznacznymi zasadami retencji
- Dodaj dokument regresyjny, gdy plik klienta ujawni nowy przypadek brzegowy
Dokumentacja produktu
Dodatkowe przykłady kodu
var
Pdf: TPDFlib;
StsId: Integer;
HashHex, TstDer, TsAttr, AugmentedCms: AnsiString;
begin
Pdf := TPDFlib.Create;
try
StsId := Pdf.NewPAdESSignatureTimeStampProcessFromFile('invoice-signed.pdf', '');
Pdf.SetPAdESSignatureTimeStampField(StsId, 'Sig1');
Pdf.SetPAdESSignatureTimeStampDigestAlgorithm(StsId, 2);
HashHex := Pdf.GetPAdESSignatureValueHashHex(StsId);
// both calls below are application code: an HTTP POST to your TSA,
// and a CMS re-encode that attaches the token as an unsigned attribute
TstDer := RequestTimeStampToken(HashHex);
TsAttr := Pdf.BuildPAdESSignatureTimeStampAttribute(TstDer);
AugmentedCms := AttachUnsignedAttribute(Pdf.GetPAdESSignatureCMSBytes(StsId), TsAttr);
Pdf.SetPAdESSignatureCMSBytes(StsId, AugmentedCms);
Pdf.EndPAdESSignatureTimeStampProcessToFile(StsId, 'invoice-bt.pdf');
if Pdf.GetPAdESSignatureTimeStampProcessResult(StsId) <> 1 then
raise Exception.Create('timestamp embedding failed');
Pdf.ReleasePAdESSignatureTimeStampProcess(StsId);
finally
Pdf.Free;
end;
end;var
Doc: TPDFlibSignDoc;
Names: TStringList;
I: Integer;
B0, B1, B2, B3, FileSize: Int64;
begin
FileSize := TFile.GetSize('invoice-bt.pdf'); // before Open: SignDoc holds a share lock
Doc := TPDFlibSignDoc.Create;
try
if not Doc.Open('invoice-bt.pdf', '', False) then
raise Exception.Create('cannot open for audit');
Names := TStringList.Create;
try
Doc.GetSignatureFieldNames(Names);
for I := 0 to Names.Count - 1 do
if Doc.GetSignatureValueObjNum(Names[I]) > 0 then // >0 means actually signed
begin
B0 := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 11)));
B1 := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 12)));
B2 := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 13)));
B3 := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 14)));
if (B0 = 0) and (B2 + B3 = FileSize) then
Writeln(Names[I], ': covers the file to EOF')
else
Writeln(Names[I], ': earlier revision, or unexpected ByteRange layout');
end;
finally
Names.Free;
end;
Doc.Close;
finally
Doc.Free;
end;
end;