HotPDF ověřuje CMS podpisy ML-DSA-44, ML-DSA-65, ML-DSA-87, Ed25519 a Ed448 v načtených PDF dokumentech a podepisuje přes výměnné providery, takže privátní klíč nikdy nemusí žít uvnitř vašeho procesu v Delphi. Právě ta druhá polovina je část, kterou většina týmů potřebuje jako první. Hardwarový token, vzdálená podepisovací služba i národní eID karta všechny odmítnou klíč vydat a dokud není podepisovací roura oddělena od úložiště klíčů, nelze použít žádný z nich
Toto rozdělení je smyslem THPDFSignatureProvider. HotPDF si ponechává části, které má vlastnit — parsování CMS, stavbu SignedData, rozložení /ByteRange — a deleguje jedinou operaci, kterou vlastnit nemůže: přeměnu digestu na podpis klíčem, který nesmí vidět. Vše, co následuje, vyplývá z tohoto rozdělení
Proč platný ML-DSA podpis neprojde ověřením?
Protože HotPDF odmítá ML-DSA na načteném dokumentu, který nedeklaruje příslušné rozšíření. ML-DSA — mřížkové schéma podpisu standardizované jako FIPS 204 a důvod, proč se říká „post-kvantové PDF" — zatím nemá v ISO 32000-2 žádnou registraci. PDF, které ho nese, používá algoritmus, který základní standard nejmenuje, a soubor, který potichu používá nepojmenovaný algoritmus, je soubor, jehož verdikt nedokáže předehrát nikdo jiný
HotPDF proto dělá tvrzení explicitním. EnsureMLDSAExtensions tam, kde je to povoleno, povýší dokument na PDF 2.0 a zapíše /Extensions /HotPDF << /BaseVersion /2.0 /ExtensionLevel 1 >> do katalogu. Na straně čtení hlásí LoadedDocumentDeclaresMLDSAExtension, zda deklarace přežila, a VerifyLoadedSignatureWithOptions aplikuje stejný test dříve, než bude respektovat Options.AllowMLDSA. Nastavte příznak na nedeklarovaném dokumentu a zůstane vypnutý — volba může povolit politiku, nikdy však strukturální požadavek
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;
Zavolejte ji před uložením, ne po něm. Deklarace je součástí podepsaného byte rozsahu a katalog patchovaný dodatečně je buď nepodepsanou změnou podepsaného souboru, nebo druhou revizí, kterou validátor ohlásí jako modifikaci
Tři rodiny algoritmů, jediný vstupní bod ověření
Všechny tři rodiny přicházejí přes VerifyLoadedSignatureWithOptions, který přijímá index podpisu, zdrojový stream, záznam THPDFCMSVerifyOptions a výstupní parametr pro detaily podpisu. Záznam má přesně tři pole a každé odpovídá na otázku, která dříve vyžadovala rebuild
SignatureProvider nahrazuje vestavěný platformní provider vaším vlastním. OpenSSLLibraryPath vybírá knihovnu OpenSSL 3, která dodává verifikaci Ed25519 a Ed448 v pure režimu, jež Windows CNG nenabízí všude. AllowMLDSA přistupuje k mřížkovým algoritmům s výhradou kontroly rozšíření výše. Přesný OID algoritmu, který byl rozpoznán, se vrací v THPDFSignatureInfo.SignatureAlgorithmOID, takže audit log může zaznamenat, co bylo ověřeno, nikoli co bylo vyžádáno
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 nepotřebují deklaraci rozšíření, protože je už ISO 32000-2 uznává. Potřebují však provider, který je implementuje, což na většině nasazení Windows znamená nasměrovat OpenSSLLibraryPath na knihovnu, kterou sami dodáváte a řídíte, nikoli na to, co se zrovna náhodou nachází v počítači
Co vlastně podepisovací provider slibuje?
Provider slibuje jedinou věc: k danému požadavku vrátit stav a při podepisování bytes. THPDFSignatureProviderRequest nese algoritmus a jeho OID, OID digestu, délku PSS soli, zda je vstup zpráva nebo už vypočtený digest, samotný vstup, veřejný klíč či certifikát, identifikátor klíče a identifikátor operace. Nic v tom záznamu není specifické pro HotPDF — je to slovník, kterým už mluví ovladač tokenu nebo podepisovací služba
S knihovnou se dodávají tři implementace. THPDFCallbackSignatureProvider obaluje anonymní metody, což je nejkratší cesta od existující interní podepisovací rutiny k funkčnímu PDF podpisu. THPDFRemoteSignatureProvider obaluje transportní callback s limitem opakování, registrací rušení a omezeními velikosti vstupu i podpisu, takže zavěšený HSM nemůže přerůst v zavěšenou aplikaci. THPDFPKCS11SignatureProvider serializuje RSA operace proti PKCS#11 sezení a handle privátního klíče, které vlastní a již autentizoval volající — HotPDF se nikdy nepřihlašuje, nikdy nevidí PIN a nikdy nezavírá sezení, které sám neotevřel
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;
Proč má stavový enum šest hodnot místo booleanu
THPDFSignatureProviderStatus rozlišuje spsValid, spsInvalid, spsUnsupported, spsMalformed, spsProviderError a spsCancelled a jejich sloučení vás stojí schopnost reagovat správně. Podpis, který je kryptograficky špatný (spsInvalid), je bezpečnostní událost. Algoritmus, který provider neimplementuje (spsUnsupported), je mezera v nasazení. Selhání transportu (spsProviderError) stojí za to zkusit znovu, kdežto uživatelem zrušený dotaz na token (spsCancelled) za to nestojí vůbec
Pravidlo pro podepisování je úzké: podepisovací provider vrací spsValid pouze s neprázdným podpisem. Verifikační providery vrací spsValid nebo spsInvalid a zbylé čtyři zůstávají na obou cestách oddělené. Pokud píšete provider, odolte pokušení mapovat cokoli nerozpoznaného na spsInvalid — to mění chybějící DLL v hlášení, že podpis zákazníka je padělaný
Kam podpis ve souboru skutečně dopadne
Dvě funkce propojují providery se skutečnými bajty PDF. HPDFCMSBuildSignedDataWithProvider staví detached CMS z digestu dokumentu SHA-256, což je správný vstupní bod, když vaše roura počítá digest jinde. HPDFCMSSignPDFStreamWithProvider podepisuje existující zástupné místo podpisu v PDF streamu a zachovává standardní pipelainu /ByteRange, což je správný vstupní bod, když HotPDF zástupné místo sám rozložil
Zachovat tu pipelainu má větší váhu, než zní. Konvence /ByteRange — dvě rozsahy, které přeskakují hex okénko podpisu — je to, co každý validátor kontroluje jako první, a cesta přes provider, která by ji přepsala, by rozbila shodu s PAdES bez ohledu na to, jak bezpečná byla kryptografie. HotPDF drží rozložení totožné s vestavěnou podepisovací cestou, takže dokument podepsaný přes PKCS#11 token projde stejným kódem pro ověření podpisu jako dokument podepsaný z PFX souboru. Pravidla profilu, která stojí nad volbou algoritmu, rozebírá průvodce baseline podpisy PAdES v Delphi a specifické encoding pasti ECDSA, které předcházely tomuto modelu providerů, poznámky k verifikaci ECDSA CMS a formátům podpisu P1363
Pořadí migrace, které nenechá vaše dokumenty na holičkách
Připravenost na post-kvantum je problém harmonogramu, ne přepínač. Téměř žádný dnes nasazený PDF prohlížeč ML-DSA nevaliduje, takže dokument podepsaný jen jím je z pohledu čtenáře dokument s neověřitelným podpisem. Pořadí, které přežije kontakt se skutečnými archivy, je: ponechte RSA nebo ECDSA jako podpis, jejž bude validátor posuzovat, přidejte deklaraci rozšíření a druhý ML-DSA podpis tam, kde politika vyžaduje kvantově odolný důkaz, a přesuňte primární podpis až ve chvíli, kdy konzumující systémy dorůstou
Co HotPDF dnes dává, je schopnost zapsat i ověřit obojí, ze stejného kódu, s algoritmem poctivě zaznamenaným v souboru i ve výsledku ověření. HotPDF je nativní VCL PDF komponenta pro Delphi a C++Builder bez externího PDF runtime, takže podepisovací i verifikační cesta žije uvnitř vašeho spustitelného souboru, nikoli vedle něj — viz stránka HotPDF Delphi PDF komponenty pro úplný seznam funkcí a zkušební stažení