Technický článek

Dlouhodobé podpisy PDF v Delphi: PAdES B-LT a B-LTA

Aby se podepsané PDF dalo ověřit i za několik let, po vypršení platnosti podepisovacího certifikátu a výměně jeho CA, dokáže komponenta PDFium Component vytvářet dlouhodobé podpisy PAdES ve Windows: časové razítko RFC 3161 pro důvěryhodný čas, Document Security Store (DSS), který integruje validační materiály, a archivní DocTimeStamp nad celým souborem. Tyto tři doplňky představují základní úrovně PAdES B-T, B-LT a B-LTA a komponenta PDFium Component jich všech dosáhne z jediného volání podepisování. Jedná se o funkci určenou pouze pro Windows, která je podmíněna vlastností PadesCryptoAvailable

Tento článek je třetím v sérii. První, podepisování PDF pomocí PAdES B-B s využitím PDFium VCL, pokrývá základní podpis; druhý, inspekce digitálních podpisů PDF a úrovní PAdES, pokrývá zpětné čtení podpisu a zjištění, jaké úrovně dosáhl. Zde se zabýváme archivem: podpisy, které musí přežít vypršení platnosti certifikátu a zůstat ověřitelné po dobu uchování měřenou v letech, nikoli v týdnech

Proč se platný podpis PDF po čase přestane ověřovat?

Základní podpis odpovídá pouze na jednu otázku: zda byly tyto bajty po podepsání změněny. Sám o sobě však nedokazuje, kdy k podepsání došlo, a tato mezera jej později znehodnotí. Struktura CMS nese atribut času podpisu, ale podepisující tuto hodnotu zapisuje ze svých vlastních hodin, takže validátor nemá důvod jí důvěřovat. Když podepisovací certifikát později vyprší nebo jej CA odvolá, přísný validátor již nedokáže odlišit podpis vytvořený v době platnosti certifikátu od podpisu zfalšovaného po jeho vypršení. Podpis byl v pořádku v den, kdy byl vytvořen, a stává se neověřitelným bez vlastního zavinění

Dlouhodobá archivace to řeší dvěma kroky. Za prvé, důvěryhodná třetí strana, autorita časového razítka (TSA), potvrzuje čas kryptograficky, takže již nezávisí na poctivosti podepisujícího. Za druhé, každý certifikát, odpověď na odvolání a CRL potřebné k sestavení a kontrole řetězce důvěry jsou integrovány přímo uvnitř PDF, takže validace nezávisí na serverech, které mohou být v době kontroly již nefunkční. PAdES, standardizovaný jako ETSI EN 319 142-1, je vrství jako základní úrovně a komponenta PDFium Component zapisuje struktury, které každá úroveň vyžaduje

Co je to podpis PDF s LTV nebo archivním časovým razítkem?

PAdES definuje čtyři základní úrovně, které na sebe navazují, a komponenta PDFium Component je vystavuje prostřednictvím výčtu TPadesLevel (plB_B, plB_T, plB_LT, plB_LTA). B-B je obyčejný podpis. B-T přidává důvěryhodné časové razítko nad hodnotu podpisu. B-LT (long-term) přidává integrované validační materiály, což je vlastnost, kterou většina lidí myslí pod pojmem „LTV“. B-LTA (long-term s archivním časovým razítkem) obaluje vše dalším časovým razítkem, které pokrývá celý soubor, takže samotný integrovaný materiál je prokazatelně neporušený od okamžiku archivace

Praktický výklad je schodiště. B-T dokazuje, kdy. B-LT dokazuje, pomocí čeho lze podpis stále kontrolovat. B-LTA dokazuje, že s celým balíčkem nebylo od jeho zapečetění manipulováno, a to je úroveň, kterou obnovujete přidáním nového DocTimeStamp dříve, než vyprší ten předchozí, čímž archiv prodloužíte na neurčito. Pro smlouvu nebo záznam o shodě s dlouhou povinností uchovávání je cílem B-LTA; B-LT je pragmatickým minimem

Schodový diagram čtyř základních úrovní PAdES produkovaných PDFium Component pro Delphi ukazující, jak B-B roste do B-T, B-LT a B-LTA
Každá úroveň přidá jeden stavební kámen — B-T váže důvěryhodný čas, B-LT vkládá validační úložiště a B-LTA zabalí zalepený soubor do obnovitelného archivního časového razítka

Přidání důvěryhodného času: PAdES B-T s RFC 3161

Komponenta PDFium Component přeměňuje podpis B-B na B-T nastavením dvou polí v TPadesSignOptions: zvyšte Level na plB_T a zadejte TsaUrl. Když jsou obě přítomny, podepisovací potrubí (pipeline) zahashuje nezpracované oktety podpisu pomocí SHA-256, zabalí tento otisk jako messageImprint pro RFC 3161, odešle požadavek na TSA přes WinHttp a vloží vrácený token jako nepodepsaný atribut signature-time-stamp (OID 1.2.840.113549.1.9.16.2.14) do unsignedAttrs [1] struktury SignerInfo, v souladu s EN 319 142-1 §6.3. Časové razítko pokrývá konkrétně hodnotu podpisu, což je to, co váže důvěryhodný čas k tomuto přesnému podpisu

uses
  PDFium, FPdfPades;

procedure SignWithTimestamp;
var
  Pdf: TPdf;
  Options: TPadesSignOptions;
begin
  Pdf := TPdf.Create(nil);
  try
    if not Pdf.PadesCryptoAvailable then
      raise Exception.Create('Podepisovací backend PAdES je pouze pro Windows');
    Pdf.FileName := 'contract.pdf';
    Pdf.Active := True;

    Options := TPadesSignOptions.Default;
    Options.CertificateThumbprint := 'A1B2C3D4E5F6071829304152637485960A1B2C3D';
    Options.Level  := plB_T;
    Options.TsaUrl := 'http://timestamp.example-tsa.com/tsr';
    Options.Reason := 'Contract execution';
    // Nonce ponecháno na 0: komponenta odvodí jedinečnou hodnotu proti opakování (anti-replay).

    Pdf.SignPades('contract-bt.pdf', Options);
  finally
    Pdf.Free;
  end;
end;

CertificateThumbprint je otisk SHA-1 (v hexadecimálním tvaru) certifikátu v úložišti Current User "MY", jehož soukromý klíč můžete použít. Pole Nonce je hodnota proti opakování (anti-replay) dle RFC 3161; ponechte ji nulovou a komponenta odvodí jedinečnou hodnotu pro každý požadavek z SHA-256 otisku čítače, hodin, počtu tiků a ID procesu, takže se dva požadavky vydané ve stejné milisekundě nestřetnou. Vlastní hodnotu předejte pouze tehdy, když máte kryptografický generátor náhodných čísel, kterému byste raději důvěřovali. Jedno upřímné upozornění: B-T vyžaduje dostupnou TSA, takže podepisování nyní provádí síťové volání a dědí dostupnost a latenci TSA

Integrovaní validačních materiálů: B-LT a B-LTA v jednom volání

Krok k dlouhodobé validaci představuje jedinou změnu: nastavte Level na plB_LTA a ponechte TsaUrl. Komponenta PDFium Component pak spustí celé schodiště v rámci jediného volání SignPades. Podepíše B-B, opatří časovým razítkem pro B-T, vloží Document Security Store pro B-LT a připojí archivní časové razítko pro B-LTA, každé jako vlastní inkrementální aktualizaci, takže dřívější bajty zůstanou netknuté

procedure SignForArchive;
var
  Pdf: TPdf;
  Options: TPadesSignOptions;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'contract.pdf';
    Pdf.Active := True;

    Options := TPadesSignOptions.Default;
    Options.CertificateThumbprint := 'A1B2C3D4E5F6071829304152637485960A1B2C3D';
    Options.Level    := plB_LTA;   // řídí B-B -> B-T -> B-LT -> B-LTA
    Options.TsaUrl   := 'http://timestamp.example-tsa.com/tsr';
    Options.Location := 'Head Office';

    // Jedno volání zapíše časové razítko, DSS a archivní DocTimeStamp.
    Pdf.SignPades('contract-lta.pdf', Options);
  finally
    Pdf.Free;
  end;
end;

Pro fázi B-LT sestaví komponenta PDFium Component řetězec certifikátů pomocí CertGetCertificateChain a zapíše slovník /DSS obsahující certifikát podepisujícího a každou zprostředkující CA v poli /Certs (s paralelními poli /OCSPs a /CRLs), spolu s identifikátorem úrovně 1 /Extensions /ESIC, přesně jak předepisuje norma EN 319 142-1 §5.4.2. Samopodepsaný root je záměrně vynechán, protože RFC 5652 §10.2.3 to umožňuje a root je již kotvou důvěry, kterou validátor drží. Výsledkem je podpis, který může čtenář ověřit pouze se samotným souborem v ruce

Pro B-LTA komponenta připojí Document Time-stamp: slovník podpisu s /SubFilter /ETSI.RFC3161, jehož /ByteRange pokrývá celý soubor, jeho /Contents nese token RFC 3161 nad tímto rozsahem a povýší identifikátor ESIC na úroveň 2. Jedná se o archivní krok dle §5.4.3 a TS 119 142-3. Protože DocTimeStamp pokrývá DSS i podpis, dokazuje, že integrovaný validační materiál byl přítomen a nezměněn v době archivace, což je přesně to, co musí dlouhodobé zásady uchovávání dokázat

Rozšíření podpisu, který již existuje

Někdy již podpis na dokumentu je a vy potřebujete pouze přidat nebo aktualizovat validační úložiště, například pro povýšení podpisu B-B od třetí strany na B-LT pro váš archiv. Komponenta PDFium Component vystavuje injektor DSS přímo přes SaveAsPadesDss, který připojuje struktury /DSS a /Extensions jako inkrementální aktualizaci bez dotčení stávajících bajtů podpisu

procedure AddValidationStore;
var
  Pdf: TPdf;
  DssOpts: TPadesDssOptions;
  Cert: TPadesDssMaterial;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'already-signed.pdf';
    Pdf.Active := True;

    DssOpts := TPadesDssOptions.Default;
    DssOpts.EsicExtensionLevel := 1;         // 1 pro B-LT, 2 pro B-LTA
    Cert.DerBytes := LoadSignerCertDer;       // váš certifikát v kódování DER
    SetLength(DssOpts.Certs, 1);
    DssOpts.Certs[0] := Cert;

    Pdf.SaveAsPadesDss('already-signed-lt.pdf', DssOpts);
  finally
    Pdf.Free;
  end;
end;

Dodáte certifikáty v kódování DER a volitelně odpovědi OCSP a CRL, které bude validátor potřebovat. Nastavte EsicExtensionLevel na 1 pro úložiště B-LT nebo 2, pokud bude následovat DocTimeStamp. Ponechte IncludeVri na výchozí hodnotě False: norma EN 319 142-1 §5.4.2.3 považuje slovník /VRI pro jednotlivé podpisy za volitelný a nedoporučuje jej, pokud jej nevyžaduje konkrétní čtenář, na kterého cílíte

Náklady a hranice, které stojí za to plánovat

Tři upřímná omezení určují, kam tyto úrovně pasují. Za prvé, kryptografický backend je pouze pro Windows: podepisování a časové razítko procházejí platformovými CNG a WinHttp úložišti, takže PadesCryptoAvailable vrací jinde False a SignPades vyvolá výjimku. Inspekce na straně čtení popsaná v doprovodném článku zůstává multiplatformní; pouze zápis podpisů je vázán na Windows. Za druhé, B-T a B-LTA závisí na autoritě časového razítka, což znamená síťový round trip v době podepisování a externí službu, jejíž dostupnost a limity četnosti se stávají součástí vaší cesty podepisování

Diagram zpátečního toku aplikace Delphi s PDFium Component posílající žádost RFC 3161 autoritě časových razítek a vkládající vrácený token
Se zvýšeným Level na plB_T a nastaveným TsaUrl komponenta hashuje podpis, získá token RFC 3161 od TSA a uloží ho jako nepodepsaný atribut

Za třetí, každá úroveň stojí úložiště. Každá fáze připojuje inkrementální aktualizaci, místo aby soubor přepisovala, DSS integruje celý řetězec certifikátů a archivní DocTimeStamp rezervuje místo pro svůj token, takže soubor B-LTA je výrazně větší než originál B-B. To je záměrný kompromis: utratíte bajty nyní, abyste si koupili ověřitelnost později. Pro většinu archivů smluv a shody je to správný kompromis, ale stojí za to jej změřit na vlastních dokumentech, místo abyste to předpokládali. Když potřebujete potvrdit, zda hotový soubor skutečně dosáhl požadované úrovně, ověřte jej pomocí technik v inspekci digitálních podpisů PDF a úrovní PAdES, a pokud zabezpečujete dokumentový potrubí šířeji, poznámky o auditu bezpečnostních rizik PDF pokrývají související kontroly

Funkce podepisování PAdES, DSS a archivního časového razítka zde ukázané jsou součástí komponenty PDFium Component pro Delphi a C++Builder, jejíž produktová stránka obsahuje kompletní referenci k podepisování a požadavky na platformu

Vrstvený diagram rozložení souboru ukazující inkrementální aktualizace, které zapíše jediné volání Delphi SignPades: hodnotu podpisu, token časového razítka, úložiště DSS a archivní DocTimeStamp
Volání plB_LTA zapíše čtyři připojené fáze — původní podpis, časové razítko podpisu, validační úložiště DSS a pak celosouborové DocTimeStamp, jež vše zalepí