Teknisk artikkel

Langsiktige PDF-signaturer i Delphi: PAdES B-LT og B-LTA

For å sikre at en signert PDF kan verifiseres om mange år, etter at signeringssertifikatet har utløpt og sertifikatutstederen (CA) er rotert, kan PDFium-komponenten produsere langsiktige PAdES-signaturer på Windows: et RFC 3161-tidsstempel for klarert tid, et Document Security Store (DSS) som bygger inn valideringsmaterialet, og et arkiv-DocTimeStamp over hele filen. Disse tre tilleggene utgjør baselinjenivåene PAdES B-T, B-LT og B-LTA, og PDFium-komponenten oppnår alle disse fra et enkelt signeringskall. Dette er en funksjon som kun støttes på Windows, beskyttet av PadesCryptoAvailable

Denne artikkelen er den tredje i en serie. Den første, signering av PDF-er med PAdES B-B ved bruk av PDFium VCL, dekker den grunnleggende signaturen; den andre, inspeksjon av PDF-digitale signaturer og PAdES-nivåer, dekker lesing av en signatur og fastsettelse av hvilket nivå den har nådd. Her er fokus på arkivet: signaturer som må overleve sertifikatutløp og forbli verifiserbare i en oppbevaringsperiode målt i år, ikke uker

Hvorfor slutter en gyldig PDF-signatur å verifiseres over tid?

En grunnleggende signatur svarer bare på ett spørsmål: ble disse bytene endret etter signering. Den beviser ikke i seg selv når signeringen skjedde, og det gapet er det som skaper problemer senere. CMS-strukturen bærer et signeringstidsattributt, men signataren skriver denne verdien fra sin egen klokke, så en validator har ingen grunn til å stole på den. Når signeringssertifikatet senere utløper eller sertifikatutstederen tilbakekaller det, kan en streng validator ikke lenger skille mellom en signatur som ble laget mens sertifikatet var gyldig, og en som ble forfalsket etter at sertifikatet utløp. Signaturen var i orden den dagen den ble laget, men blir uverifiserbar uten at det er signaturens egen feil

Langsiktig arkivering løser dette på to måter

For det første vil en klarert tredjepart, en tidsstempelautoritet (TSA), bekrefte tidspunktet kryptografisk, slik at det ikke lenger avhenger av signatarens ærlighet. For det andre blir alle sertifikater, tilbakekallingssvar og CRL-er som trengs for å bygge og sjekke tillitskjeden bygget inn i selve PDF-en, slik at valideringen ikke er avhengig av servere som kan være borte når noen sjekker den. PAdES, som er standardisert som ETSI EN 319 142-1, strukturerer disse som baselinjenivåer, og PDFium-komponenten skriver strukturene som hvert nivå krever

Hva er en LTV- eller arkiv-tidsstemplert PDF-signatur?

PAdES definerer fire baselinjenivåer som bygger på hverandre, og PDFium-komponenten eksponerer dem gjennom TPadesLevel-opptellingen (plB_B, plB_T, plB_LT, plB_LTA). B-B er den vanlige signaturen. B-T legger til et klarert tidsstempel over signaturverdien. B-LT (langsiktig) legger til det innebygde valideringsmaterialet, egenskapen de fleste mener med "LTV". B-LTA (langsiktig med arkivtidsstempel) pakker alt inn i enda et tidsstempel som dekker hele filen, slik at det innebygde materialet i seg selv beviselig er intakt fra arkiveringstidspunktet

Den praktiske tolkningen er en trapp. B-T beviser når. B-LT beviser med hva signaturen fortsatt kan sjekkes. B-LTA beviser at hele pakken ikke har blitt endret siden den ble forseglet, og det er nivået du fornyer ved å legge til et nytt DocTimeStamp før det forrige utløper, for å utvide arkivet på ubestemt tid. For en kontrakt eller en samsvarsprotokoll med lang oppbevaringsplikt er B-LTA målet; B-LT is det pragmatiske minimumet

Legge til klarert tid: PAdES B-T med RFC 3161

PDFium-komponenten gjør en B-B-signatur om til B-T ved å angi to felt i TPadesSignOptions: sett Level til plB_T og oppgi en TsaUrl. Når begge er til stede, vil signeringsrørledningen hashe de rå signaturoktettene med SHA-256, pakke dette sammendraget som RFC 3161 messageImprint, sende forespørselen til TSA-en over WinHttp og bygge inn det returnerte tokenet som det usignerte attributtet for signaturtidsstempel (OID 1.2.840.113549.1.9.16.2.14) i SignerInfos unsignedAttrs [1], i henhold til EN 319 142-1 §6.3. Tidsstempelet dekker spesifikt signaturverdien, som er det som binder den klarerte tiden til akkurat den signaturen

uses
  PDFium, FPdfPades;

procedure SignWithTimestamp;
var
  Pdf: TPdf;
  Options: TPadesSignOptions;
begin
  Pdf := TPdf.Create(nil);
  try
    if not Pdf.PadesCryptoAvailable then
      raise Exception.Create('PAdES signing backend is Windows-only');
    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 left at 0: the component derives a unique anti-replay value.

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

Bygge inn valideringsmateriale: B-LT og B-LTA i ett enkelt kall

Trinnet opp til langsiktig validering er en enkelt endring: sett Level til plB_LTA og behold TsaUrl. PDFium-komponenten kjører da hele trappen i ett enkelt SignPades-kall. Den signerer B-B, tidsstempler for B-T, injiserer Document Security Store for B-LT, og legger til arkivtidsstempelet for B-LTA, hver som sin egen trinnvise oppdatering slik at de tidligere bytene forblir intakte byte-for-byte

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;   // drives B-B -> B-T -> B-LT -> B-LTA
    Options.TsaUrl   := 'http://timestamp.example-tsa.com/tsr';
    Options.Location := 'Head Office';

    // One call writes the timestamp, the DSS and the archive DocTimeStamp.
    Pdf.SignPades('contract-lta.pdf', Options);
  finally
    Pdf.Free;
  end;
end;

For B-LT-trinnet bygger PDFium-komponenten sertifikatkjeden med CertGetCertificateChain og skriver en /DSS-ordbok som bærer signatursertifikatet pluss hver mellomliggende CA i en /Certs-tabell (med parallelle /OCSPs- og /CRLs-tabeller), sammen med en /Extensions /ESIC-markør på Nivå 1, nøyaktig slik EN 319 142-1 §5.4.2 foreskriver. Den selvsignerte roten utelates bevisst, siden RFC 5652 §10.2.3 tillater det og roten allerede er et tillitsanker validatoren besitter. Resultatet er en signatur en leser kan verifisere utelukkende med filen i hånden

For B-LTA legger komponenten til et Document Time-stamp: en signaturordbok med /SubFilter /ETSI.RFC3161 der /ByteRange spenner over hele filen, /Contents inneholder et RFC 3161-token over dette området, og den oppgraderer ESIC-markøren til Nivå 2. Dette er arkiveringstrinnet i §5.4.3 and TS 119 142-3. Fordi DocTimeStamp dekker både DSS og signaturen, beviser det at det innebygde valideringsmaterialet var til stede og uendret på arkiveringstidspunktet, noe som er nøyaktig det en langsiktig oppbevaringspolicy må kunne vise

Utvide en eksisterende signatur

Noen ganger er signaturen allerede på dokumentet, og du trenger bare å legge til eller oppdatere valideringslageret, for eksempel for å bringe en tredjeparts B-B-signatur opp til B-LT for arkivet ditt. PDFium-komponenten eksponerer DSS-injektoren direkte gjennom SaveAsPadesDss, som legger til /DSS- og /Extensions-strukturene som en trinnvis oppdatering uten å røre de eksisterende signaturbytene

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 for B-LT, 2 for B-LTA
    Cert.DerBytes := LoadSignerCertDer;       // your DER-encoded certificate
    SetLength(DssOpts.Certs, 1);
    DssOpts.Certs[0] := Cert;

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

Du oppgir de DER-kodede sertifikatene, og eventuelt OCSP-svar og CRL-er som en validator vil trenge. Sett EsicExtensionLevel til 1 for et B-LT-lager, eller 2 når et DocTimeStamp skal følge etter. La IncludeVri være standard False: EN 319 142-1 §5.4.2.3 behandler signatur-spesifikke /VRI-ordbøker som valgfrie og råder mot dem med mindre en bestemt leser du retter deg mot krever det

Kostnader og grenser verdt å planlegge for

Tre begrensninger bestemmer hvor disse nivåene passer inn. For det første er den kryptografiske motoren Windows-only: signering og tidsstempling går gjennom plattformens CNG- og WinHttp-lagre, så PadesCryptoAvailable returnerer False andre steder, og SignPades feiler. Den skrivebeskyttede inspeksjonen som dekkes i den tilhørende artikkelen forblir på tvers av plattformer; bare skriving av signaturer er bundet til Windows. For det andre avhenger B-T og B-LTA av en tidsstempelautoritet (TSA), noe som betyr en nettverksforespørsel ved signering og en ekstern tjeneste der oppetid og hastighetsgrenser blir en del av signeringsbanen din

For det tredje koster hvert nivå lagringsplass. Hvert trinn legger til en trinnvis oppdatering i stedet for å skrive om filen, DSS bygger inn en full sertifikatkjede, og arkiv-DocTimeStamp reserverer plass til sitt token, så en B-LTA-fil er betydelig større enn den opprinnelige B-B-filen. Dette er et bevisst bytteforhold: du bruker byte nå for å kjøpe verifiserbarhet senere. For de fleste kontrakts- og samsvarsarkiver er det det rette valget, men det er verdt å måle på dine egne dokumenter i stedet for å anta. Når du trenger å bekrefte at en ferdig fil faktisk nådde nivået du ønsket, kan du verifisere den med teknikkene i inspeksjon av PDF-digitale signaturer og PAdES-nivåer, og hvis du herder en dokumentrørledning mer generelt, dekker notatene om revisjon av PDF-sikkerhetsrisikoer de øvrige sjekkene

Funksjonene for PAdES-signering, DSS og arkivtidsstempel vist her er en del av PDFium Component for Delphi og C++Builder, der produktsiden inneholder den fullstendige signeringsreferansen og plattformkravene