HotPDF overuje ML-DSA-44, ML-DSA-65, ML-DSA-87, Ed25519 a Ed448 CMS podpisy v načítaných PDF dokumentoch a podpisuje cez pripojiteľných providerov, takže súkromný kľúč nikdy nemusí žiť vo vnútri vášho Delphi procesu. Druhá polovica je časť, ktorú väčšina tímov potrebuje ako prvú. Hardvérový token, vzdialená podpisová služba a národná eID karta všetky odmietajú vydať kľúč a kým nie je podpisová linka oddelená od úložiska kľúčov, nedá sa použiť žiadny z nich
Toto oddelenie je zmyslom THPDFSignatureProvider. HotPDF si ponecháva časti, ktoré má vlastniť — parsing CMS, stavbu SignedData, rozmiestnenie /ByteRange — a deleguje jedinú operáciu, ktorú vlastniť nemôže, a to premenu digestu na podpis kľúčom, ktorý nesmie vidieť. Všetko ďalšie vyplýva z tohto rozdelenia
Prečo platný ML-DSA podpis zlyhá pri overovaní?
Pretože HotPDF odmieta ML-DSA na načítanom dokumente, ktorý nedeklaruje príslušné rozšírenie. ML-DSA — mriežkový podpisový schéma štandardizovaný ako FIPS 204 a dôvod, prečo ľudia hovoria „post-kvantové PDF" — nemá zatiaľ žiadnu registráciu v ISO 32000-2. PDF, ktoré jeden nesie, používa algoritmus, ktorý základný štandard nemenuje, a súbor, ktorý potichu používa nepomenovaný algoritmus, je súbor, ktorého verdikt nedokáže zopakovať nikto iný
Tak HotPDF robí nárok explicitným. EnsureMLDSAExtensions zvýši dokument na PDF 2.0, kde je to povolené, a zapíše /Extensions /HotPDF << /BaseVersion /2.0 /ExtensionLevel 1 >> do katalógu. Na čítacej strane LoadedDocumentDeclaresMLDSAExtension hlási, či táto deklarácia prežila, a VerifyLoadedSignatureWithOptions aplikuje ten istý test skôr, než bude rešpektovať Options.AllowMLDSA. Nastavte príznak na nedeklarovanom dokumente a zostane vypnutý — voľba môže uvoľniť politiku, nikdy však štrukturálny predpoklad
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'contract-pq.pdf';
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 720, 0, 'Supply agreement 2026-114');
Pdf.EnsureMLDSAExtensions; // declare before the signature is written
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Zavolajte to pred uložením, nie po ňom. Deklarácia je súčasťou podpísaného rozsahu bajtov a katalóg opravený dodatočne je buď nepodpísanou zmenou podpísaného súboru, alebo druhou revíziou, ktorú validátor nahlási ako modifikáciu
Tri rodiny algoritmov, jeden vstupný bod overovania
Všetky tri rodiny prichádzajú cez VerifyLoadedSignatureWithOptions, ktorý prijíma index podpisu, zdrojový stream, záznam THPDFCMSVerifyOptions a out parameter s detailmi podpisu. Záznam má presne tri polia a každé odpovedá na otázku, ktorá kedysi vyžadovala prestavbu
SignatureProvider nahradzuje vstavaný platformný provider tým vaším. OpenSSLLibraryPath vyberá knižnicu OpenSSL 3, ktorá dodáva overovanie Ed25519 a Ed448 v režime pure-mode, ktoré Windows CNG neponúka všade. AllowMLDSA zapája mriežkové algoritmy, podmienene kontrolou rozšírenia vyššie. Presný OID algoritmu, ktorý bol rozpoznaný, sa vráti v THPDFSignatureInfo.SignatureAlgorithmOID, takže audit log môže zaznamenať, čo bolo overené, a nie čo bolo požadované
var
Opts: THPDFCMSVerifyOptions;
Info: THPDFSignatureInfo;
Status: THPDFSignatureVerifyStatus;
Src: TFileStream;
begin
Opts := THPDFCMSVerifyOptions.Default;
Opts.OpenSSLLibraryPath := 'C:\openssl3\libcrypto-3-x64.dll';
Opts.AllowMLDSA := Pdf.LoadedDocumentDeclaresMLDSAExtension;
Src := TFileStream.Create('contract-pq.pdf', fmOpenRead or fmShareDenyWrite);
try
Status := Pdf.VerifyLoadedSignatureWithOptions(0, Src, Opts, Info);
if Status = svValid then
Memo1.Lines.Add('signed with OID ' + string(Info.SignatureAlgorithmOID));
finally
Src.Free;
end;
end;
Ed25519 a Ed448 nepotrebujú deklaráciu rozšírenia, pretože ISO 32000-2 ich už pripúšťa. Potrebujú však providera, ktorý ich implementuje, čo na väčšine Windows nasadení znamená nasmerovať OpenSSLLibraryPath na knižnicu, ktorú dodávate a ovládate vy, a nie na to, čo sa náhodou nachádza na stroji
Čo podpisový provider skutočne sľubuje?
Provider sľubuje jednu vec: prijatím požiadavky vráti stav a pri podpisovaní aj bajty. THPDFSignatureProviderRequest nesie algoritmus a jeho OID, OID digestu, dĺžku PSS soli, či vstup je správa alebo už vypočítaný digest, samotný vstup, verejný kľúč alebo certifikát, identifikátor kľúča a identifikátor operácie. Nič v tomto zázname nie je špecifické pre HotPDF — je to slovník, ktorým už hovorí ovládač tokenu alebo podpisová služba
S knižnicou sa dodávajú tri implementácie. THPDFCallbackSignatureProvider obaľuje anonymné metódy, čo je najkratšia cesta od existujúcej interného podpisovej rutiny k fungujúcemu PDF podpisu. THPDFRemoteSignatureProvider obaľuje transportný callback s limitom opakovaní, registrom zrušenia a ohraničeniami veľkosti vstupu a podpisu, takže zatuhnuté HSM sa nemôže stať zatuhnutou aplikáciou. THPDFPKCS11SignatureProvider serializuje RSA operácie voči volajúcim vlastnenej, už autentifikovanej PKCS#11 relácii a handle súkromného kľúča — HotPDF sa nikdy neprihlasuje, nikdy nevidí PIN a nikdy nezatvára reláciu, ktorú sám neotvoril
var
Provider: THPDFRemoteSignatureProvider;
begin
Provider := THPDFRemoteSignatureProvider.Create(
function(const Req: THPDFSignatureProviderRequest; Attempt: Integer;
out Signature: TBytes): THPDFSignatureProviderStatus
begin
// POST Req.Input to the signing service; Req.KeyIdentifier selects the key
if PostToSigningService(Req.KeyIdentifier, Req.Input, Signature) then
Result := spsValid
else
Result := spsProviderError;
end,
3, // RetryLimit
1048576, // MaxInputBytes
65536); // MaxSignatureBytes
try
// hand Provider to the signing call
finally
Provider.Free;
end;
end;
Prečo má enum stavu šesť hodnôt namiesto boolu
THPDFSignatureProviderStatus odlišuje spsValid, spsInvalid, spsUnsupported, spsMalformed, spsProviderError a spsCancelled a ich zrútenie vás pripraví o schopnosť konať správne. Podpis, ktorý je kryptograficky chybný (spsInvalid), je bezpečnostná udalosť. Algoritmus, ktorý provider neimplementuje (spsUnsupported), je medzera v nasadení. Zlyhanie transportu (spsProviderError) sa oplatí opakovať a používateľom zrušený prompt tokenu (spsCancelled) sa neoplatí opakovať vôbec
Pravidlo pre podpisovanie je úzke: podpisový provider vráti spsValid iba s nepráznym podpisom. Overovací provideri vracajú spsValid alebo spsInvalid a ostatné štyri zostávajú odlišné na oboch cestách. Ak píšete providera, odolávajte pokušeniu mapovať všetko, čo nerozpoznáte, na spsInvalid — to zmení chýbajúce DLL na hlásenie, že podpis zákazníka je sfalšovaný
Kde podpis skutočne pristanuje v súbore
Dve funkcie prepájajú providerov s reálnymi PDF bajtmi. HPDFCMSBuildSignedDataWithProvider stavia oddelený CMS z digestu dokumentu SHA-256, čo je správny vstupný bod, keď váš workflow počíta digest inde. HPDFCMSSignPDFStreamWithProvider podpisuje existujúci zástupný podpis v PDF streame a zachováva štandardnú linku /ByteRange, čo je správny vstupný bod, keď HotPDF rozmiestnil zástupné miesto sám
Zachovanie tejto linky má väčší význam, než to znie. Konvencia /ByteRange — dva rozsahy, ktoré preskakujú hex okno podpisu — je to, čo validátor kontroluje ako prvé a cesta založená na providerovi, ktorá by ju prepísala, by zlomila zhodu s PAdES bez ohľadu na to, aká bola kryptografia správna. HotPDF drží rozvrhnutie identické s vstavanou podpisovou cestou, takže dokument podpísaný cez PKCS#11 token sa overí tým istým kódom overovania podpisov ako ten podpísaný z PFX súboru. Pre pravidlá profilu, ktoré sedia nad voľbou algoritmu, pozri návod k PAdES baseline podpisom v Delphi a pre ECDSA-špecifické pasce enkódovania, ktoré predchádzajú tomuto modelu providera, poznámky k ECDSA CMS overovaniu a formátom podpisu P1363
Poradie migrácie, ktoré nenechá vaše dokumenty v štoku
Post-kvantová pripravenosť je problém harmonogramu a nie prepínač. Takmer žiadny nasadený PDF prehliadač dnes ML-DSA nevaliduje, takže dokument podpísaný iba ním je z pohľadu čítačky dokument s nepreveriteľným podpisom. Poradie, ktoré prežije kontakt s reálnymi archívmi, je: ponechať RSA alebo ECDSA ako podpis, ktorý bude validátor posudzovať, pridať deklaráciu rozšírenia a druhý ML-DSA podpis tam, kde politika vyžaduje kvantovo odolný dôkaz, a presunúť primárny podpis až vtedy, keď konzumujúce systémy dobehli
Čo vám HotPDF dnes dáva, je schopnosť zapisovať a overovať obe z toho istého kódu, s algoritmom úprimne zaznamenaným v súbore aj vo výsledku overovania. HotPDF je natívny VCL PDF komponent pre Delphi a C++Builder bez externého PDF runtime, takže podpisové a overovacie cesty putujú vo vnútri vášho spustiteľného súboru a nie vedľa neho — kompletný zoznam funkcií a skúšobnú stiahnutie nájdete na stránke HotPDF Delphi PDF komponentu