HotPDF verifiserer digitale signaturer i lastede PDF-dokumenter gjennom tre THotPDF-metoder: GetLoadedSignatureInfo, VerifyLoadedSignature og VerifyLoadedSignatureEx, introdusert i v2.259.0. Komponenten re-hasher /ByteRange-segmentene til den opprinnelige filen, kontrollerer CMS-attributtet messageDigest og kjører en RSA PKCS#1 v1.5-verifisering mot det innebygde signatørsertifikatet, og returnerer svValid når dokumentets byte er intakte
Scenarioet er ordinært, men innsatsen er ikke det. En motpart returnerer en signert kontrakt, arbeidsflyten din må arkivere den, og noen stiller det eneste spørsmålet som betyr noe: er dette dokumentet vi sendte, byte for byte, signert med sertifikatet det hevder? Å besvare dette i kode er verifikasjonssiden av signaturhistorien; signeringssiden, det å bygge og bygge inn PAdES-signaturer i utgangspunktet, dekkes i ledsagerartikkelen om oppretting av PAdES digitale signaturer med HotPDF. Denne artikkelen handler om den andre retningen: en PDF ankommer ferdig signert, og du ønsker en programmatisk avgjørelse fremfor et skjermbilde av Acrobats grønne hake
Hvordan beviser en signert PDF at den ikke har blitt tuklet med?
En PDF-signatur beskytter spesifikke byteområder i filen, ikke en abstrakt forestilling om "dokumentet". ISO 32000-1 §12.8 definerer mekanismen: signaturskjema-feltet bærer en ordbok hvis /Contents-oppføring inneholder en CMS SignedData-beholder (RFC 5652), og hvis /ByteRange-array navngir de nøyaktige filområdene signaturen dekker, i henhold til §12.8.1. Arrayen er en liste over forskyvnings- og lengdepar, i praksis to segmenter: alt før heksadesimalstrengen /Contents, og alt etter den. Signaturverdien kan ikke dekke seg selv, så filen hashes rundt det hullet
Det designet har en konsekvens som former hele API-et: verifiseringen må hashe de opprinnelige serialiserte bytene, nøyaktig slik de ligger på disken. En analysert objektmodell er ubrukelig til dette, fordi det å re-serialisere selv et uendret dokument produserer andre byte. HotPDF verifiserer derfor mot kildefilen dokumentet ble lastet fra, eller mot en TStream med rå byte som du oppgitt, aldri mot dens representasjon i minnet
Lese signatur-metadata før du verifiserer noe
GetLoadedSignatureInfo tolker signaturordboken og dens CMS-beholder uten å berøre en eneste dokumentbyte, noe som gjør det til det riktige første kallet når du bare trenger å vise hvem som signerte og når. Signaturfelt er indeksert fra 0 i skjema-felt-rekkefølge, og GetLoadedSignatureFieldCount forteller deg hvor mange som finnes. Den returnerte THPDFSignatureInfo-posten bærer feltnavnet, /SubFilter, signatørsertifikatets fellesnavn, emne- og utstederidentifikasjonsnavn, serienummer, gyldighetsdatoer, signeringstidspunktet (fra det signerte attributtet når det er til stede, ellers ordbokens /M-oppføring), digest-algoritmenavnet og strengene /Reason, /Location og /ContactInfo. Dens Status-medlem forblir svNotVerified, en ærlig merknad for "analysert, ikke sjekket"
Kjøre den kryptografiske sjekken
VerifyLoadedSignatureEx utfører den fullstendige verifiseringen for et fillastet dokument og leverer tilbake den fylte infoposten i ett kall: den gjenåpner kildefilen, hasher /ByteRange-segmentene med digest-algoritmen til SignerInfo, sammenligner resultatet med det signerte attributtet messageDigest (RFC 5652 §5.4), og RSA-verifiserer deretter signaturen over DER SET-re-kodingen av de signerte attributtene. Når en signatur ikke har noen signerte attributter, kjøres RSA-sjekken direkte over dokumenthashen i stedet. Støttede signaturer er RSA PKCS#1 v1.5 med SHA-1, SHA-256, SHA-384 eller SHA-512 digester, som dekker underfiltrene adbe.pkcs7.detached og ETSI.CAdES.detached produsert av vanlige signeringsverktøy
To implementasjonsdetaljer er verdt å kjenne til fordi de forklarer feil som ser mystiske ut fra utsiden. For det første er sjekken av signerte attributter kresen på kodingen: inne i filen er attributtene merket med [0] IMPLICIT, men signaturen ble beregnet over deres DER SET OF-form, så verifikatoren merker om før hashing, nøyaktig slik RFC 5652 §5.4 krever. En hjemmelaget verifikator som hasher bytene slik de vises i filen, vil avvise alle riktig signerte dokumenter. For det andre er /Contents konvensjonelt null-polstret (zero-padded) til et reservert bytebudsjett, så verifikatoren korter ned DER-bloben til den faktiske lengden på dens ytre SEQUENCE før tolking; trailing nuller som ser ut som søppel er normalt, ikke korrupsjon. Den samme familien av ASN.1-tolkefarer, på sertifikatimport-siden, er temaet for artikkelen om PKCS#12- og ASN.1-sikkerhetsherding i HotPDF
Hva garanterer egentlig en gyldig signatur?
svValid betyr nøyaktig dette: bytene navngitt i /ByteRange hasher til verdien signatøren signerte, og signaturen verifiseres under den offentlige nøkkelen til sertifikatet som er bygd inn i CMS-beholderen. Det er byte-integritet pluss nøkkelbinding, og ingenting mer. Sertifikatkjede- og tillitsvalidering er eksplisitt utenfor omfanget for HotPDFs verifikator: den går ikke kjeden til en rot, sjekker tilbakekalling eller konsulterer noe tillitslager. Et selvsignert sertifikat fra en angriper som signerte et endret dokument på nytt vil verifiseres som svValid, fordi matematikken er internt konsistent. Om signatøren er den de hevder å være, og om noen bør stole på dem, er en policybeslutning som hører hjemme i et separat lag, enten det er organisasjonens sertifikathvitliste, Windows' sertifikatlager eller en valideringsinstans
Flagget CoversWholeDocument sikrer et mer subtilt gap. En signatur dekker alltid bare sin /ByteRange, og PDFs mekanisme for inkrementelle oppdateringer tillater å legge til innhold etter en signatur uten å gjøre den ugyldig, noe som er tilsiktet og hvordan arbeidsflyter med flere signaturer fungerer. Flagget beregnes under verifisering og er sant kun når de to segmentene pluss /Contents-gapet spenner over hele filen. Når svValid ankommer med CoversWholeDocument usann, er den signerte revisjonen intakt, men filen inneholder later additions, and what those additions changed is something your workflow should decide whether to tolerate
Strømlastede og krypterte dokumenter trenger sine egne kildebyte
De parameterløse VerifyLoadedSignature og VerifyLoadedSignatureEx avhenger av at komponenten husker hvilken fil dokumentet kom fra. Laster du dokumentet fra en strøm, er det ikke noe filnavn å gjenåpne; det samme gjelder etter passord-reinnlastingsbanen som brukes for krypterte dokumenter, arbeidsflyten beskrevet i artikkelen om AES-256 PDF-kryptering med HotPDF. I begge tilfeller returnerer de filbaserte overlastingene svSourceUnavailable i stedet for å gjette. Løsningen er TStream-overlastingen, som lar deg overlevere de opprinnelige rå bytene fra der du oppbevarte dem, en fil du fremdeles har, en minnebuffer, en databaseblob
var
Src: TFileStream;
Status: THPDFSignatureVerifyStatus;
Info: THPDFSignatureInfo;
begin
// Stream-loaded document: the component holds no source
// file name, so supply the original bytes yourself.
Src := TFileStream.Create('signed-contract.pdf',
fmOpenRead or fmShareDenyWrite);
try
Status := Pdf.VerifyLoadedSignature(0, Src, Info);
if Status <> svValid then
Writeln('Verification failed: ', Ord(Status));
finally
Src.Free;
end;
end;
Rapportere hva du ikke kan verifisere
En verifikator som bare kjenner til "gyldig" og "ugyldig" vil feilrapportere dokumenter den rett og slett ikke forstår, så statusopptellingen skiller tilfellene brukergrensesnittet ditt bør skille. svDigestMismatch betyr at dokumentets byte ble endret etter signering, det klassiske tegnet på tukling. svSignatureInvalid betyr at bytene hashes riktig, men RSA-sjekken feilet, noe som peker på en skadet eller forfalsket signaturverdi. svUnsupportedAlgorithm er det ærlige svaret for ECDSA-nøkler og ukjente digester: signaturen kan være helt fin, HotPDF kan bare ikke kontrollere den, og å rapportere det som "ugyldig" ville sverte et sunt dokument. svMalformed flagger en CMS-beholder som ikke kunne tolkes i det hele tatt. For kontroller i portstil returnerer VerifyAllLoadedSignatures sant kun når minst ett signaturfelt eksisterer og hver av dem verifiseres som svValid, en praktisk enkelt boolsk verdi for en pipeline for dokumentmottak som avviser alt annet
Signatureverifisering, PAdES-signering, AES-256-kryptering og API-et for redigering av lastede dokumenter leveres alle i det samme native VCL-biblioteket for Delphi og C++Builder, uten eksterne DLL-avhengigheter; den fullstendige funksjonslisten og støttede IDE-versjoner finnes på produktsiden for HotPDF Component