Et tillatelsesflagg er ingen sikkerhetsmekanisme. Biten som sier «ingen kopiering», bor i den samme /Encrypt-ordboken som kryptografien, noe som gir den et skjær av håndhevelse den ikke har, og i det øyeblikket du behandler de to som én ting, begynner granskingen din å produsere gale svar. Det eneste spørsmålet som er verdt å stille en PDF, er ikke «er den kryptert». Det er mer spesifikt og vanskeligere: hvilken algoritme, hvilken revisjon av sikkerhetsbehandleren, hvilket av de to passordene som ble satt, hvilke tillatelsesbiter som påstås, og hvilke deler av filen krypteringen faktisk berører. En fil kan være formelt kryptert og praktisk talt åpen. Den kan nekte å bli lest og likevel la metadataene ligge i klartekst. Den kan sperre utskrift i et flagg enhver leser står fritt til å overse. Å granske en PDF betyr å avgjøre alt dette hver for seg, og PDF Library for Delphi, losLabs PDF-motor for Delphi og C++Builder, eksponerer hver av delene både gjennom et flatt API med heltallshåndtak og gjennom et typet klasselag
Hva /Encrypt-ordboken faktisk noterer
ISO 32000-1 §7.6 definerer dokumentsikkerhet gjennom en håndfull ordbokoppføringer, og PDF Library for Delphi speiler dem én-til-én i posten TPDFEncryption. Filterversjonen V og revisjonen R velger algoritmefamilien. Length bærer nøkkelstørrelsen. Tillatelsesbitene sitter i P, valideringsstrengene for eier- og brukerpassordet i O og U (med OE og UE lagt til for AES-256), et EncryptMetadata-flagg følger med, og tre felter til navngir kryptfiltrene som brukes på henholdsvis strenger, strømmer og innebygde filer
Verdien av denne posten er at den ikke tolker noe for deg. Den gir tilbake den rå ordboken og lar deg trekke konklusjonene, som er nettopp det en gransking trenger. Tilfellet klartekst-inni-kryptert dukker opp i StringFilterIdentity og StreamFilterIdentity: når én av dem er sann, går de tilsvarende dataene urørt gjennom Identity-filteret, uansett hva dokumentets krypteringsstatus melder. En skanner som stopper ved «det finnes en /Encrypt-ordbok», vil kalle en slik fil beskyttet mens strengene og strømmene ligger åpne. Den samme nyansen styrer metadata. Når EncryptMetadata er usann, forblir XMP-pakken lesbar for enhver indekserer mens sideinnholdet ikke er det, noe som er verdt å vite i det øyeblikket rutingreglene dine bygger på et tittel- eller forfatterfelt
En kort sikkerhetssonde med det flate API-et
For de fleste pipeliner svarer fire flate kall på hverdagsspørsmålene. LoadFromFile returnerer 1 ved suksess, og når dokumentet først er åpent, rapporterer krypteringsinspektørene mot dets dekrypterte tilstand:
var
PDF: TPDFlib;
begin
PDF := TPDFlib.Create;
try
if PDF.LoadFromFile('contract.pdf', UserPassword) <> 1 then
raise Exception.Create('Open failed: wrong password or damaged file');
Writeln('status : ', PDF.EncryptionStatus); // dekryptert / kryptert / ukjent
Writeln('algorithm : ', PDF.EncryptionAlgorithm); // RC4 mot AES-familien
Writeln('strength : ', PDF.EncryptionStrength); // nøkkellengdeklasse
Writeln('owner pw? : ', PDF.CheckPassword(CandidatePassword));
finally
PDF.Free;
end;
end;
CheckPassword betyr mer enn signaturen på én linje antyder. PDF definerer to passord med ulik makt. Brukerpassordet kreves for i det hele tatt å åpne filen. Eierpassordet gir fulle rettigheter og overstyrer hver tillatelsesbit. Bytene på disk er identiske uansett, men en økt åpnet med eierpassordet kan gjøre ting en økt med brukerpassordet ikke kan, så en gransking som ikke noterer hvilken legitimasjon som ble lagt fram, noterer bare halve sannheten. Klasselaget gjør skillet spørrbart. TPDFDocument.HasUserPassword og HasOwnerPassword melder hva filen krever, mens IsUserPassword og IsOwnerPassword melder hvilket passord som faktisk åpnet den gjeldende økten. Logg det faktumet. Logg aldri selve passordverdiene
Strength-stigen, der «AES-256» betyr to ting
De flate funksjonene Encrypt og EncryptFile tar et heltall Strength med fem meningsbærende verdier: 0 for 40-bits RC4, 1 for 128-bits RC4, 2 for 128-bits AES lesbar fra Acrobat 7, 3 for 256-bits AES slik den kom med Acrobat 9, og 4 for 256-bits AES slik Acrobat X og senere krever
Det interessante er at 3 og 4 begge merkes AES-256 og likevel ikke er samme ordning. Strength 3 svarer til revisjon 5 av sikkerhetsbehandleren, et mellomliggende design Acrobat 9 leverte og ISO aldri tok inn. Strength 4 svarer til revisjon 6, hvis nøkkelavledningsfunksjon ble herdet og standardisert i ISO 32000-2. For et dokument du lager i dag, finnes det ingen grunn til å velge 3 framfor 4. For en gransking er gapet avgjørende: en policy som lyder «AES-256 etter ISO 32000-2», oppfylles av R6 alene, og en R5-fil som kaller seg AES-256, stryker på den policyen mens den består en naiv styrkekontroll. Klasselaget holder de to fra hverandre ved navn, esAES256Bit for R5 mot esAES256BitAcroX for R6, og egenskapen EncryptionAcroX svarer på revisjonsspørsmålet med én enkelt boolsk verdi
Tillatelsesbiter og finskriften om nøkkellengde
EncodePermissions pakker åtte flagg inn i heltallet som Encrypt og EncryptFile forventer. Utskrift, kopiering, endring og notattillegg utgjør grunnsettet; skjemautfylling, kopiering for tilgjengelighet, sammenstilling og utskrift i full kvalitet utgjør det utvidede settet. Finskriften, som bibliotekets egen krypteringsdemo sier rett ut, er at de fire utvidede først trer i kraft ved 128-bits styrke og oppover. Flagget for utskrift i full kvalitet faller under samme regel: nullstill det for å tvinge fram lavoppløst utskrift, og et 40-bits dokument overser deg, fordi den nedgraderingen også krever 128-bits eller sterkere kryptering. Kod en policy om «bare lavoppløst utskrift» inn i en 40-bits fil, og enhver leser skriver ut i full kvalitet likevel
Det dypere spørsmålet er hvem som håndhever noen av disse bitene, og svaret er ingen du kan stole på. Tillatelser er instruksjoner til lesere som følger standarden, ikke kryptografiske begrensninger. Dekrypteringsnøkkelen er den samme enten kopiering er tillatt eller nektet, så et nedlåst tillatelsessett holder bare ærlige lesere ærlige. En leser som velger å overse bitene, møter ingen kryptografisk hindring i det hele tatt. Er plikten å hindre uttrekk snarere enn å motvirke det, trenger filen et brukerpassord og arbeidsflyten prosessnivåkontroller rundt seg, og en granskingsrapport bør navngi hvilket av de to regimene hver fil faktisk står under, framfor å behandle et tillatelsesflagg som en lås
Å sette policy og bevise at den festet seg
Å bruke kryptering på eksisterende filer krever ikke at de lastes inn i objekttreet. EncryptFile behandler inndata til utdata i ett enkelt kall, og granskingssløyfen åpner resultatet på nytt for å bekrefte hva som landet på disk. Krypteringsdemoen som følger med, har samme form med skriving og påfølgende tilbakelesing:
var
PDF: TPDFlib;
R: Integer;
begin
PDF := TPDFlib.Create;
try
R := PDF.EncryptFile('in.pdf', 'out.pdf', 'owner-secret', 'user-secret', 4,
PDF.EncodePermissions(1, 0, 0, 0, // utskrift tillatt; kopiering/endring/notater nektet
0, 0, 0, 1)); // utvidet sett: bare utskrift i full kvalitet
if (R = 1) and (PDF.LoadFromFile('out.pdf', 'user-secret') = 1) then
begin
Writeln('algorithm = ', PDF.EncryptionAlgorithm);
Writeln('strength = ', PDF.EncryptionStrength);
Writeln('owner pw accepted: ', PDF.CheckPassword('owner-secret'));
end;
finally
PDF.Free;
end;
end;
Team som arbeider på dokumentlaget, får den samme operasjonen med typede mengder i stedet for bitpakking, noe som overlever kodegjennomgang med langt mindre myseøyne:
if not Doc.Encrypt('owner-secret', 'user-secret', esAES256BitAcroX,
[ppCanPrint], [ppCanPrintFull]) then
raise Exception.Create('Encryption failed');
Uansett vei er tilbakelesingstrinnet ikke valgfri seremoni. Det fanger utrullingsfeilene som ellers dukker opp måneder senere på en kundemaskin: et gammelt bibliotekbygg som stilltiende nedgraderer den forespurte styrken, en utdatasti som aldri ble skrevet fordi katalogen var skrivebeskyttet, et tillatelsesheltall der argumentene kom i feil rekkefølge. Alle tre består en lokal røyktest og feiler ute i felten, og å åpne utdataene på nytt gjør hver av dem til et unntak du ser under den kjøringen som lagde filen. GetEncryptionFingerprint returnerer en kompakt verdi du kan lagre sammen med jobbposten, slik at en senere sammenligning kan avgjøre om to utdatafiler deler den samme krypteringskonfigurasjonen uten å åpne noen av dem
Falske positive i gransking som er verdt å kode for
Noen få mønstre skyver pålitelig sikkerhetsskannere mot feil konklusjon, og hvert av dem kommer av å presse et flerdelt spørsmål ned til et ja eller nei. Identity-kryptfilteret er det reneste eksempelet. En /Encrypt-ordbok finnes, filen melder seg som kryptert, og likevel går strengene og strømmene uendret gjennom Identity-filteret, så det virkelige innholdet er klartekst. Å lese StringFilterIdentity og StreamFilterIdentity før du erklærer noe som helst beskyttet, er løsningen
Metadataskillet er finere. EncryptMetadata kan være uenig med resten av dokumentet i begge retninger, og etterlate en kryptert fil med en lesbar XMP-pakke eller, sjeldnere, det motsatte. «Filen er kryptert» sier ingenting om hvorvidt metadataene er det, noe som betyr noe i det øyeblikket en indekserer eller en rutingregel griper etter tittelen. Innebygde filer legger til en tredje akse: PDF tillater et eget kryptfilter kun for vedlegg, så vedleggene kan være den eneste krypterte delen av et ellers åpent dokument, eller den eneste klartekstdelen av et kryptert. Fang de tre filtertildelingene som separate felter for strenger, strømmer og innebygde filer, så kan ingen av disse fellene ta deg. Lagre én enkelt boolsk verdi, og feilvurderingen er bare et tidsspørsmål
Å fjerne kryptering, og å velge den for nye filer
En gransking ender ofte i en beslutning om å strippe beskyttelsen, og mekanikken er ikke hindringen der. DecryptFile(InputFileName, OutputFileName, Password) skriver en dekryptert kopi uten full lasting, og Decrypt på et lastet dokument gjør det samme i minnet når en fil allerede er åpen. Begge krever et gyldig passord; ingen av dem omgår kryptografien. Den virkelige porten er policy snarere enn kode, så la mottaksreglene dine si rett ut når fjerning er tillatt, og noter passordklassen som ga fullmakt, for selve det tekniske trinnet etterlater ingen spor
Valget for nye utdata er snevrere enn de fem Strength-verdiene antyder. Bruk Strength 4, AES-256 revisjon 6, med mindre du må åpne filer i lesere eldre enn Acrobat X. Strength 2, AES-128, er det pragmatiske gulvet for en aldrende leserpark som ikke kan oppgraderes. RC4-valgene på 0 og 1 finnes for at du skal kunne lese og granske historiske arkiver, ikke for at du skal produsere noe nytt med dem; å gripe etter dem i et design fra 2026 er et tegn på at et krav lenger oppstrøms er foreldet
Krypteringstilstanden mater rett inn i signeringsbeslutninger, siden en arbeidsbenk som validerer og signerer dokumenter, trenger den samme tilbakelesingsdisiplinen denne granskingen hviler på. Det terrenget dekkes i artikkelen om arbeidsbenken for samsvar og signering. Når en batch kjører EncryptFile over tusenvis av store dokumenter, viser guiden til direkte tilgang for store PDF-er hvordan du holder minnebruken flat mens den går. Den fullstendige API-referansen for kryptering finnes på produktsiden for PDF Library for Delphi