Komponenta HotPDF Delphi PDF izvaja model kriptografskih filtrov ISO 32000-1 §7.6.5 kot tri neodvisne politike namesto enega stikala: ConfigureCryptFilterDefaults ločeno določi filter nizov /StrF, filter tokov /StmF in filter vdelanih datotek /EFF, SetStreamCryptFilter preglasi posamezni tok, GetLoadedCryptFilterInfo pa poroča, kaj razglaša vhodna datoteka. Večina težav interoperabilnosti šifriranih PDF-jev živi v vrzelih med temi tremi
Tu je napaka, ki ljudi pripelje v to plast. Ekipa pošlje dokument, v katerem mora vsebina strani ostati berljiva za nadaljnje orodje, priloženi tovor pa ne, zato nastavi /EFF /StdCF in pusti /StmF /Identity. Acrobat ga odpre brez težav. Skladen bralnik drugega proizvajalca vrne prilogo kot smeti šifriranega besedila, ker je /EFF politika na strani izdelovalca o tem, kateri filter velja za vdelane datoteke, splošni bralnik pa neoznačeni tok še vedno razreši prek /StmF. Popravek ni drugačna vrednost /EFF. Popravek je izrecen filter /Crypt na samem toku vdelane datoteke
Kaj plast kriptografskih filtrov dejansko nadzoruje
Kriptografski filtri sedijo med algoritmom šifriranja in grafom objektov ter odločajo, katere objekte algoritem doseže, ne pa, kako deluje. Slovar /CF znotraj šifrirnega slovarja preslika imena v definicije filtrov, vsaka pa vsebuje metodo /CFM, neobvezni /Length in /AuthEvent. Trije vnosi na vrhu, /StrF, /StmF in /EFF, nato izberejo, kateri od imenovanih filtrov velja za nize, tokove brez izrecnega filtra in vdelane datoteke. HotPDF namerno omejuje, kaj bodo njegovi vgrajeni obravnavalniki zapisali. ConfigureCryptFilterDefaults sprejme samo rezervirana imena za aktivni obravnavalnik: obravnavalnik Standard izda /StdCF ali /Identity, obravnavalnik javnega ključa izda /DefaultCryptFilter ali /Identity, vse drugo pa na mestu klica sproži EArgumentException. Filtri, ki jih z drugimi imeni zapišejo zunanji izdelovalci, se pri nalaganju, pregledu in združljivem ponovnem pisanju še vedno ohranijo, zato je HotPDF kot zapisovalnik konservativen, kot bralnik pa permisiven. Veljata še dve varovali: klic sproži EInvalidOpException, ko se serializacija dokumenta že začne, in znova, če je dokument v inkrementalni posodobitvi, ker se politika šifriranja med revizijami iste datoteke ne more spremeniti
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.AutoLaunch := False;
Pdf.FileName := 'wrapper.pdf';
Pdf.OwnerPassword := 'owner-secret';
Pdf.UserPassword := 'open-secret';
Pdf.CryptKeyLength := aes128;
// nizi so šifrirani, tokovi strani so odprto besedilo, priloge so šifrirane
Pdf.ConfigureCryptFilterDefaults('StdCF', 'Identity', 'StdCF');
Pdf.ActivateProtection := True;
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 12);
Pdf.CurrentPage.TextOut(50, 50, 0, 'Visible stream operators');
Pdf.AddDocumentAttachment('payload.bin', 'Encrypted payload');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Eno omejitev je vredno povedati takoj, ker se preveri pozno in ljudi preseneti. Imenovani kriptografski filtri v HotPDF zahtevajo šifriranje dokumenta z aes128, aes256 ali aesgcm. Nastavite politiko filtra nad RC4 k40 ali k128 in validacijski prehod, ki se izvede ob vklopu šifriranja, sproži napako, namesto da bi tip ključa tiho povišal. To je isto stališče kot pri preostali poti šifriranja PDF-ja AES-256 v Delphiju: zavrnite dvoumno konfiguracijo, namesto da ugibate, kaj je klicatelj mislil
Zakaj vnos /Length pomeni dve različni stvari?
Ker ga specifikacija glede na varnostni obravnavalnik določa v dveh različnih enotah in mora HotPDF upoštevati obe. V slovarju kriptografskega filtra, katerega /CFM je /V2, je vnos /Length pri obravnavalniku Standard izražen v bajtih, pri obravnavalniku javnega ključa pa v bitih. /Length v šifrirnem slovarju, ki stoji ob /V (ISO 32000-1 §7.6.2), je vedno v bitih. Preberite slovar filtra z /Length 16 in dobili ste 128-bitni ključ v datoteki z obravnavalnikom Standard ter zavrnjeno datoteko pri obravnavalniku javnega ključa. HotPDF to normalizira, ko zajame naloženo konfiguracijo. Filter /V2 pomnoži /Length z osem samo, ko datoteka ni šifrirana z javnim ključem, če filter nima lastnega vnosa, uporabi /Length na ravni dokumenta in rezultat shrani v THPDFCryptFilterInfo.KeyLengthBits. AESV2 je fiksiran na 128 bitov, AESV3 in AESV4 pa na 256, saj pri teh metodah velikosti ključa ni mogoče pogajati. Strogi del pride nato: sprejmeta se samo 40-bitni in 128-bitni /V2. Filter, ki se razreši v katero koli drugo dolžino, se javi kot nedosegljiv in operacija odpove, namesto da bi ga zaokrožili na 128 z mislijo, da je večina izdelovalcev tako ali tako mislila 128. Tiha normalizacija dolžine ključa je način, kako dostavite datoteko, ki se dešifrira na vašem računalniku in nikjer drugje
var
Reader: THotPDF;
Info: THPDFCryptFilterInfo;
I: Integer;
begin
Reader := THotPDF.Create(nil);
try
Reader.AutoLaunch := False;
if Reader.LoadFromFile('incoming.pdf', 'open-secret') <> 1 then
Exit;
// /StrF in /StmF sta privzeto Identity; /EFF je privzeto /StmF
WriteLn(Reader.LoadedStringCryptFilterName); // StdCF
WriteLn(Reader.LoadedStreamCryptFilterName); // Identity
WriteLn(Reader.LoadedEmbeddedFileCryptFilterName); // StdCF
for I := 0 to Reader.GetLoadedCryptFilterCount - 1 do
if Reader.GetLoadedCryptFilterInfo(I, Info) then
if (Info.Method = hcfmV2) and
not (Info.KeyLengthBits in [40, 128]) then
raise Exception.CreateFmt(
'crypt filter /%s: unsupported V2 key length %d',
[String(Info.Name), Info.KeyLengthBits]);
finally
Reader.Free;
end;
end;
Kaj zagotavlja /CFM /None in kako se razlikuje /Identity?
Do istega rezultata prideta po različnih poteh, njuno mešanje pa pokvari iskanje. Imenovani filter, katerega /CFM je /None, in imenovani filter, ki /CFM povsem izpusti, oba pomenita, da ta filter ne šifrira in ne dešifrira ničesar — HotPDF manjkajoči vnos pred razreševanjem preslika v None, zato oba končata pri hcfmNone z zabeleženo dolžino ključa 0. /Identity je drugačen po naravi: to je rezervirano ime, ki v celoti obide iskanje v /CF, zato se dokument lahko sklicuje na /Identity, ne da bi ga kjer koli definiral v /CF. Imena PDF so občutljiva na velikost črk, zato je še ena podrobnost izvedbe neizpogajljiva: nobeno iskanje kriptografskega filtra ne sme biti neobčutljivo na velikost črk. HotPDF podimena slovarja /CF, vnos /Length filtra in preverjanje toka /Type razrešuje z iskanji slovarjev, občutljivimi na velikost črk. Datoteka, ki definira /stdcf, medtem ko /StmF kaže na /StdCF, je napačna, obravnava obeh kot istega ključa pa bi zaznavno napako pri izdelavi spremenila v tiho uporabo napačnega ključa za vsak tok dokumenta
Kako zagotoviti, da /EFF ostane na tokovih vdelanih datotek
Ko se /EFF razlikuje od /StmF, tok vdelane datoteke potrebuje izrecen začetni vnos /Crypt v svojem /Filter in ujemajoči se slovar /DecodeParms z /Name na istem položaju polja. HotPDF to izračuna za vsak tok ob shranjevanju: zazna /Type /EmbeddedFile, podeduje konfigurirani filter vdelanih datotek in izda izrecno oznako /Crypt samo, ko se podedovano ime razlikuje od učinkovite privzete vrednosti toka. Ko se /EFF in /StmF ujemata, oznaka ni zapisana, ker bi bralnik tako ali tako razrešil isti filter. Položaj v polju je nato enako pomemben kot ime. Ko HotPDF tok prebere nazaj, poišče vnos /Crypt v /Filter, zabeleži njegov indeks in nato isti indeks poišče v polju /DecodeParms, da najde /Name. /Crypt na indeksu 0, povezan s parametri na indeksu 1, se razreši v /Identity, ne v vaš filter. Zato zapisovalnik polje parametrov dopolni z ničelnim elementom, ko je tok prej imel /Filter, ne pa /DecodeParms: položaja morata ostati poravnana
V ozadju je še ostrejša past. Če sta obstoječa /Filter ali /DecodeParms posredni objekt — kar je običajno pri datotekah iz izdelovalcev, ki eno polje filtrov delijo med več tokovi — bi vstavljanje /Crypt na mestu spremenilo deljeni graf filtrov in pokvarilo vsak drug tok, ki kaže nanj. HotPDF posredni objekt razreši in ga najprej klonira v neposredni objekt, zaseben za tok, pri čemer počisti številki objekta in generacije, tako da izvorni posredni koren nikoli ni vdelan v novo polje. Pri toku, ki je že uporabljal ASCIIHexDecode, je serializiran rezultat /Filter [ /Crypt /ASCIIHexDecode ] z /DecodeParms [ << /Type /CryptFilterDecodeParms /Name /StdCF >> ... ]. Ista disciplina položajev ureja vsako drugo verigo filtrov, tudi tiste, po katerih hodite pri izločanju slik iz naloženega PDF-ja prek njihovih dekodirnih filtrov
// Editor že vsebuje naložen dokument, ContentStream pa je
// THPDFStreamObject, katerega /Filter je posredni naziv /ASCIIHexDecode
Editor.OwnerPassword := 'owner-secret';
Editor.UserPassword := 'open-secret';
Editor.CryptKeyLength := aes128;
Editor.ConfigureCryptFilterDefaults('StdCF', 'Identity');
Editor.SetStreamCryptFilter(ContentStream, 'StdCF');
Editor.ActivateProtection := True;
Editor.SaveLoadedDocument('out.pdf');
// Prazno ime odstrani preglasitev in ob naslednjem shranjevanju odstrani
// zastareli vnos /Crypt skupaj z njegovimi dekodirnimi parametri
Editor.SetStreamCryptFilter(ContentStream, '');
Editor.SaveLoadedDocument('cleared.pdf');
Ali objektni tokovi podedujejo politiko dokumenta /Encrypt?
Ne, domneva, da jo, pa je zanesljiv način za izdelavo smeti. Objektni tok mora slediti dejanski politiki /StmF ali lastni izrecni oznaki /Crypt: sama prisotnost slovarja /Encrypt še ne spremeni vsakega vsebnika /ObjStm v šifriran šifropis. Dokument z /StmF /Identity ima odprte objektne tokove, čeprav so njegovi nizi v celoti šifrirani, dekodirnik, ki jih kljub temu dešifrira, pa v fazo napihovanja posreduje vhod, ki nikoli ni bil izhod stiskanja deflate
Posledica za članske objekte je del, ki ga je vredno prebrati dvakrat. Po ISO 32000-1 §7.5.7 so nizi znotraj šifriranega objektnega toka že odprto besedilo, ko je dešifriran vsebnik, zato bi njihovo ponovno dešifriranje pomenilo dvojno dešifriranje. HotPDF to varuje tako, da preveri, ali je bil vsebnik vsakega objekta tipa 2 šifriran, in objekt preskoči, ko je bil, preskoke pa šteje v XRefProbeDecryptObjStmSkips kot neposreden dokaz, da se je varovalo sprožilo. Ko je bil vsebnik odprto besedilo, članski nizi niso bili z ničimer pokriti, zato HotPDF te člane materializira in na vsakega posebej uporabi /StrF — ključi jih, kot to dejansko počne izvedba, s številko in generacijo članskega objekta, ne s številko vsebujočega objekta /ObjStm. Če to obrnete pri datoteki z mešano politiko, se vsak niz v vsakem stisnjenem objektu dekodira v šum. Pravila na ravni vsebnika so podrobneje obravnavana v zapiskih o objektnih tokovih PDF in inkrementalnih posodobitvah
Kje HotPDF noče ugibati
Semantika kriptografskih filtrov pod /V 4 ne obstaja, zato HotPDF vsako preglasitev po toku pri taki datoteki zavrne z izrecno napako, namesto da bi zapisal oznako /Crypt, ki je noben skladen bralnik ne bi upošteval. Enako velja na strani branja: šifrirni slovar z /V pod 4 počisti vsa tri imena naloženih filtrov, ker tam ni ničesar, o čemer bi lahko poročal. Tri nadaljnje meje se uveljavijo namerno:
- Filter po toku, ki ni
Identity, se pri dokumentu, šifriranem z javnim ključem, zavrne, ker politika po toku pri obravnavalniku javnega ključa potrebuje ovoj prejemnika po toku, ki ga HotPDF še ne izdaja - Vdelane datoteke, šifrirane z javnim ključem, katerih
/EFFse razlikuje od učinkovitega/StmF, se iz istega razloga zavrnejo, namesto da bi bile zapisane v obliki, ki je nihče ne more dešifrirati - Hitra pot AES-256 za neposredno delo z datoteko velja samo, ko se nizi, tokovi in vdelane datoteke vsi razrešijo v isto metodo kriptografskega filtra in noben objekt v datoteki nima izrecnega
/Crypt; mešana politika ali odprti metapodatki prisilijo vrnitev na polno pot grafa objektov
Nobena od teh odločitev ni izvedena zaradi zmogljivosti. Označujejo mesta, kjer napačna domneva ustvari PDF, ki se odpre v enem pregledovalniku, odpove v drugem in razvijalcu ne da nobenega signala, dokler ga o tem ne obvesti stranka. Zavrnitev pri ConfigureCryptFilterDefaults ali ob shranjevanju stane eno izjemo; tiho napačno zaklenjena vdelana datoteka stane cel cikel podpore. Če izdelujete programsko opremo v Delphiju ali C++Builderju, ki ustvarja ali porablja šifrirane PDF-je — selektivno odprto vsebino strani s šifriranimi prilogami, ovojne vsebnike šifriranih tovorov PDF 2.0 ali interoperabilnost z datotekami, katerih politik kriptografskih filtrov niste izbrali — je tukaj opisan API kriptografskih filtrov del trenutne komponente HotPDF Delphi PDF, skupaj s potmi šifriranja, objektnih tokov in inkrementalnih posodobitev, na katerih temelji