Teknisk artikkel

PAdES LTV-bevis og seed values i HotPDF

En PDF du nettopp har signert, er en B-B-signatur og ikke mer. Den beviser hvem som signerte og at bytene ikke har flyttet seg, men den bærer intet bevis for at signatarsertifikatet var gyldig ved signeringstidspunktet, så en validator år fra nå må lete etter tilbakekallsdata som kanskje ikke lenger finnes. Å lukke det gapet betyr å skrive OCSP-responser og CRL-er inn i dokumentnivåets Document Security Store, og i HotPDF er det ett kall: PopulatePAdESLTVEvidence går gjennom hver lastet signatur, utleder tilbakekallsforespørslene fra sertifikatsettet, utfører dem gjennom en transport du leverer, og skriver det hentede materialet pluss CMS-kjeden inn i DSS. Den returnerer antall signaturer hvis bevis landet, eller minus én når dokumentet ikke har noe signaturfelt i det hele tatt

Designavgjørelsen verdt å forstå før du bruker den, er at biblioteket aldri åpner en socket. Hver byte som ankommer fra nettverket, ankommer gjennom en callback du skrev. Det er ikke forsiktighet for sin egen skyld; det er den eneste måten denne funksjonen kan fungere inne i miljøene som faktisk krever langtidsvalidering

Hvorfor nekter biblioteket å gjøre sin egen HTTP?

Fordi stedene som krever B-LT-signaturer, er stedene der et bibliotek ikke kan tiltrues nettverket. Signeringstjenester kjører bak autentiserende proxyer med bedriftsrot-CA-er. Luftgappede signeringstier har ingen rute til en responder og må fores med bufret bevis. Revisjonsregimer krever at hver utgående forespørsel logges av applikasjonen, ikke begraves i en avhengighet. Og testpakker trenger deterministiske responser, noe som er umulig hvis biblioteket ringer ut på egen hånd

Transporten er en ren funksjonsreferanse med fast form, så politikken forblir din. HotPDF gir deg en forespørselsrecord som beskriver nøyaktig hva som skal hentes, inkludert innholdstypen og en tak for responsstørrelse, og du returnerer bytene pluss en status

HotPDF PopulatePAdESLTVEvidence-flyt: den kaller-leverte FetchEvidence-transporten, forespørselsrecordfeltene og per-signatur-statusutfall
Hver nettverksbyte passerer gjennom din FetchEvidence-callback, og hver signatur får sin egen status så ett tidsavbrudd aldri avbryter gjennomkjøringen
function FetchEvidence(const Request: THPDFSignatureEvidenceRequest;
  Attempt: Integer; CancellationToken: THPDFCancellationToken;
  out Response: TBytes; out RetryAfterMS: Cardinal;
  out ErrorMessage: UnicodeString): THPDFSignatureEvidenceTransportStatus;
begin
  RetryAfterMS := 0;
  try
    // Request.Kind sier om dette er en OCSP POST eller en CRL GET;
    // Request.ContentType og Request.Body er allerede forberedt,
    // og Request.MaxResponseBytes er taket du må respektere
    Response := HttpExchange(Request.URI, Request.ContentType,
      Request.Body, Request.MaxResponseBytes);
    Result := setsSucceeded;
  except
    on E: Exception do
    begin
      ErrorMessage := E.Message;
      // setsRetry lar retry-policyen trekke seg tilbake; bruk
      // setsPermanentFailure for en 404 eller en dårlig URL
      Result := setsRetry;
    end;
  end;
end;

// Én-kalls B-B til B-LT-oppgradering for hver signatur i den lastede filen
var
  Pdf: THotPDF;
  Upgraded: Integer;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.BeginIncrementalUpdate('signed.pdf');
    Upgraded := Pdf.PopulatePAdESLTVEvidence(FetchEvidence,
      THPDFSignatureEvidenceRetryPolicy.Default);
    if Upgraded > 0 then
      // Kun-tilleggs-lagring: bytene eksisterende signaturer dekker
      // bevares ordrett
      Pdf.SaveIncrementalUpdate('signed-lt.pdf');
  finally
    Pdf.Free;
  end;
end;

Feiler er per signatur, ikke per dokument. En responder som tidsavbryter for én signatar, hopper over den signatarens materiale og lar resten av gjennomkjøringen være intakt, noe som er oppførselen du vil ha i en batch: delvis bevis slår en avbrutt kjøring, og returverdien forteller deg hvor mange signaturer som faktisk ble forbedret

Kjeden CMS glemte å inkludere

Tilbakekallssjekking trenger utstedersertifikatet, og et overraskende antall signeringsstakker utelater intermediater fra CMS-beholderen. Gjenopprettingsruten er Authority Information Access-utvidelsen, tilgangsmetode 1.3.6.1.5.5.7.48.2, som annonsere en URL der utstedersertifikatet kan lastes ned. HPDFFetchAIAIntermediates går gjennom de URL-ene via samme transport, parser DER-en ut av hver respons, og returnerer bare sertifikatene CMS-en ikke allerede bar, nøklet etter DER-hash slik at duplikater og løkker ikke kan spinne

To detaljer avgjør om dette fungerer mot ekte sertifikatmyndigheter. Den første er koding: CA-endepunkter serverer sertifikatet som naken DER omtrent like ofte som de serverer det PEM-pansret, og det finnes ingen pålitelig innholdstype å skille dem med. Den robuste proben er tekstlig, deretter strukturell. Se etter -----BEGIN CERTIFICATE------markøren, strip pansringen og dekod base64 hvis den er til stede, og i begge veier bekreft at den første byten av resultatet er $30, DER-taggen for en SEQUENCE. Den andre er dybde: et hentet intermediat kan selv annonsere en AIA-URL for sin egen utsteder, så gjennomgangen appender nye kandidater til køen og fullfører kjeder som er to eller tre hopp for korte. Det må takseres, noe som er det MaxFetch-parameteren er til for

AIA-kjedefullførelsesdiagram for HotPDF: caIssuers URL-henting, PEM mot DER-probe, DER-hash-deduplisering og MaxFetch-dybdetaket
HPDFFetchAIAIntermediates går gjennom caIssuers-URL-er via samme transport, sonderer PEM-pansring og takserer køen med MaxFetch

Hva er en signatur seed value, og hvorfor feiler den lydløst?

En seed value er en begrensning dokumentforfatteren fester til et signaturfelt for å fortelle signataren hva slags signatur som er akseptabel: hvilken SubFilter, hvilken digest-algoritme, hvilke årsaker, hvilken minimum PDF-versjon, om tilbakekallsinformasjon må innebygdes. Den bor i en /SV-ordbok på feltet og er definert i ISO 32000-1 §12.7.5.5. HotPDF skriver den med AttachPAdESSeedValue og sjekker den med CheckLoadedSignatureSeedValue, som returnerer True når feltet er ubegrenset eller enhver til stede værende begrensning passerer, og ved False navngir den første feilende begrensningen gjennom en utdataparameter du kan legge rett inn i en feilmelding

Mekanismen som gjør seed values lette å ta feil på, er /Ff-flaggoppføringen beskrevet i §12.7.5.5.3. En satt bit merker sin begrensning som påkrevd: et avvik er en feil og signataren må nekte. En ren bit merker samme begrensning som en preferanse: verdien filtrerer hva UI-et bør tilby og ikke mer. To feller følger av det. For det første bor /Ff inne i /SV-ordboken, ikke på widget-annotasjonen, så kode som leser feltnivåets /Ff får et tomt svar for alltid og konkluderer med at ingenting er påtvunget. For det andre er bittildelingene ikke en enkel rekke av én, to, fire, åtte; i HotPDF sender skriveren ut 2 for SubFilter, 4 for MinVersion, 32 for AddRevInfo og 64 for DigestMethod. En leser som antar sekvensielle biter, dekoder hver begrensning som valgfri og passerer hver test unntatt den som betyr noe

Seed value flaggbit-tabell for HotPDF PAdES-signering som viser Ff-biter 2, 4, 32 og 64 og påkrevd mot foretrukket begrensninghåndtering
/Ff-oppføringen bor inne i /SV, og hver bitposisjon avgjør om et avvik er en hard nektelse eller en UI-preferanse
var
  Violation: AnsiString;
begin
  // Spør feltet om profilen vi er i ferd med å signere med er tillatt
  if not Pdf.CheckLoadedSignatureSeedValue(0, 'ETSI.CAdES.detached',
       'SHA256', 'Approved for payment', 1, Violation) then
    raise Exception.Create('Signature field rejects this profile: ' +
      String(Violation));
  // Begrensning oppfylt: fortsett med signeringsgjennomkjøringen
end;

Testen som avdekket den opprinnelige dekodefeilen, var ikke en positiv test. Det var påstanden om at et påtvunget avvik må avvises, og det er den eneste typen test som kan fange denne klassen av defekter: en dekoder som leser feil ordbok eller feil bitposisjoner produserer «ingen begrensninger brutt» for hver input, noe som ser nøyaktig ut som korrekt oppførsel til du bevisst bryter én

Hvor dette sitter på LTV-stigen

Fire trinn, og hvert trenger det under seg. B-B er den nakne signaturen. B-T legger til et tiltrudt tidsstempel, som fikser signeringstidspunktet slik at en validator vet hvilket øyeblikk den skal evaluere tilbakekall mot. B-LT legger til tilbakekallsbeviset i DSS, noe som er det PopulatePAdESLTVEvidence automatiserer. B-LTA legger til dokumenttidsstempler som fornyes før det forrige svekkes, og utvider gyldigheten på ubestemt tid; HotPDF eksponerer det som RenewPAdESLTATimestamp, som appender et nytt tidsstempel som en inkrementell revisjon og bevarer hver tidligere signatur, tidsstempel og DSS-oppføring urørt

En inkrementell oppdateringsmodell er den eneste korrekte måten å legge bevis til et signert dokument på, fordi å omskrive filen ville bryte byteområdene eksisterende signaturer dekker. Hvis du trenger å resonnere om hva som endret seg mellom revisjoner, og om de endringene er av den sorten en signatur tillater, er den analysen dekket separat i DocMDP- og FieldMDP-revisjonsanalysen. Signeringspipelinen selv, inkludert sertifikatkilder og byte-rekkefølge-fellgruver, står i PAdES-signeringsgjennomgangen, og valideringssiden står i verifisering av signaturer på lastede dokumenter

Én praktisk advarsel om rekkefølge. Samle bevis så snart som mulig etter signering, ideelt i den samme jobben. Responderne som kan svare for et sertifikat, er på nett mens sertifikatet er gjeldende og borte år senere, så et dokument som forlater pipelinen din som B-B, kan kanskje aldri oppgraderes igjen. HotPDF kjører som en nativ VCL-komponent for Delphi og C++Builder, og hele bevisgjennomkjøringen er i prosessen unntatt din egen transport; de støttede profilene er oppført på produktsiden for HotPDF Delphi PDF component