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

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í

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