Az engedélyjelző nem biztonsági mechanizmus. Az a bit, amely azt mondja, hogy „másolás tilos”, ugyanabban az /Encrypt szótárban lakik, mint a kriptográfia, ami olyan kikényszerítési látszatot kölcsönöz neki, amivel nem rendelkezik, és abban a pillanatban, ahogy a kettőt egy dolognak veszi, az auditja rossz válaszokat kezd gyártani. Egy PDF-ről nem azt érdemes megkérdezni, hogy titkosított-e. A kérdés ennél pontosabb és nehezebb: melyik algoritmus, a biztonsági kezelő melyik revíziója, a két jelszó közül melyiket állították be, mely engedélybiteket állítja a fájl, és a titkosítás valójában a fájl mely részeit érinti. Egy fájl lehet formálisan titkosított és gyakorlatilag nyitott. Megtagadhatja az olvasást, miközben a metaadatait nyílt szövegben hagyja. Letilthatja a nyomtatást egy olyan jelzőben, amelyet bármelyik megjelenítő nyugodtan figyelmen kívül hagyhat. Egy PDF auditálása azt jelenti, hogy mindezt külön-külön tisztázzuk, és a PDF Library for Delphi, a losLab PDF-motorja Delphihez és C++Builderhez, mindegyiket elérhetővé teszi egy lapos, egész számú leírókkal dolgozó API-n és egy típusos osztályrétegen keresztül is
Mit rögzít valójában az /Encrypt szótár
Az ISO 32000-1 §7.6 néhány szótárbejegyzésen keresztül definiálja a dokumentumbiztonságot, és a PDF Library for Delphi ezeket egy az egyben leképezi a TPDFEncryption rekordban. A V szűrőverzió és az R revízió választja ki az algoritmuscsaládot. A Length hordozza a kulcsméretet. Az engedélybitek a P mezőben ülnek, a tulajdonosi és a felhasználói jelszó ellenőrző sztringjei az O és az U mezőben (AES-256 esetén az OE és az UE is hozzájuk társul), mellettük utazik egy EncryptMetadata jelző, és további három mező nevezi meg a sztringekre, a folyamokra, illetve a beágyazott fájlokra alkalmazott titkosítószűrőket
Ennek a rekordnak az az értéke, hogy semmit nem értelmez Ön helyett. Visszaadja a nyers szótárat, és a következtetést Önre bízza, márpedig pontosan erre van szüksége egy auditnak. A titkosítotton belüli nyílt szöveg esete a StringFilterIdentity és a StreamFilterIdentity mezőben mutatkozik meg: ha bármelyik igaz, a megfelelő adat érintetlenül halad át az Identity szűrőn, függetlenül attól, mit jelent a dokumentum titkosítási állapota. Az a szkenner, amely megáll annál, hogy „van /Encrypt szótár”, védettnek fogja mondani az ilyen fájlt, miközben a sztringjei és folyamai nyíltan hevernek. Ugyanez az árnyalat vonatkozik a metaadatokra. Ha az EncryptMetadata hamis, az XMP csomag minden indexelő számára olvasható marad, miközben az oldaltartalom nem, és ezt abban a pillanatban érdemes tudni, amint az útválasztási szabályai egy cím- vagy szerzőmezőre épülnek
Rövid biztonsági szonda a lapos API-val
A legtöbb futószalag mindennapi kérdéseire négy lapos hívás felel. A LoadFromFile siker esetén 1-et ad vissza, és amint a dokumentum nyitva van, a titkosítási vizsgálók a visszafejtett állapotáról jelentenek:
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); // visszafejtett / titkosított / ismeretlen
Writeln('algorithm : ', PDF.EncryptionAlgorithm); // RC4 vagy AES család
Writeln('strength : ', PDF.EncryptionStrength); // kulcshossz-osztály
Writeln('owner pw? : ', PDF.CheckPassword(CandidatePassword));
finally
PDF.Free;
end;
end;
A CheckPassword többet számít, mint amennyit egysoros szignatúrája sejtet. A PDF két, nem egyenlő erejű jelszót definiál. A felhasználói jelszó ahhoz kell, hogy a fájl egyáltalán megnyíljon. A tulajdonosi jelszó teljes jogot ad, és minden engedélybitet felülír. A lemezen lévő bájtok mindkét esetben azonosak, de a tulajdonosi jelszóval nyitott munkamenet olyasmit is megtehet, amit a felhasználói jelszavas nem, tehát az az audit, amely nem jegyzi fel, melyik hitelesítő adatot mutatták be, az igazság felét jegyzi fel. Az osztályréteg lekérdezhetővé teszi a különbséget. A TPDFDocument.HasUserPassword és a HasOwnerPassword arról szól, mit követel meg a fájl, míg az IsUserPassword és az IsOwnerPassword arról, melyik jelszó nyitotta meg ténylegesen az aktuális munkamenetet. Ezt a tényt naplózza. Magukat a jelszóértékeket soha
A Strength-létra, ahol az „AES-256” két dolgot jelent
A lapos Encrypt és EncryptFile függvény egész számú Strength értéket vár, öt értelmes értékkel: 0 a 40 bites RC4, 1 a 128 bites RC4, 2 a 128 bites AES az Acrobat 7 óta olvashatóan, 3 a 256 bites AES az Acrobat 9 által bevezetett formában, 4 pedig a 256 bites AES az Acrobat X és újabb változatok által megkövetelt formában
Az érdekes az, hogy a 3 és a 4 egyaránt AES-256 címkét visel, és mégsem ugyanaz a séma. A 3-as erősség az 5-ös biztonságikezelő-revíziónak felel meg, egy átmeneti tervnek, amelyet az Acrobat 9 szállított, az ISO viszont soha nem fogadott el. A 4-es erősség a 6-os revízióhoz tartozik, amelynek kulcsleszármaztató függvényét megerősítették és az ISO 32000-2 szabványba emelték. Egy ma készülő dokumentumnál semmi ok a 3-at választani a 4 helyett. Egy auditnál a különbség döntő: az „ISO 32000-2 szerinti AES-256” szövegű szabályt egyedül az R6 elégíti ki, és egy magát AES-256 néven nevező R5 fájl elbukik ezen a szabályon, miközben egy naiv erősségvizsgálaton átmegy. Az osztályréteg névvel tartja szét a kettőt, az R5 az esAES256Bit, az R6 az esAES256BitAcroX, az EncryptionAcroX tulajdonság pedig egyetlen logikai értékkel felel a revízió kérdésére
Engedélybitek és apró betűs kulcshossz-feltételeik
Az EncodePermissions nyolc jelzőt csomagol abba az egész számba, amelyet az Encrypt és az EncryptFile vár. Az alapkészletet a nyomtatás, a másolás, a módosítás és a jegyzetelés adja; a bővített készletet a mezőkitöltés, az akadálymentességi másolás, az összeállítás és a teljes minőségű nyomtatás. Az apró betűs rész, amelyet a könyvtár saját titkosítási demója nyíltan ki is mond, az, hogy a bővített négy csak 128 bites és afölötti erősség mellett lép életbe. A teljes minőségű nyomtatás jelzőjére ugyanez a szabály áll: törölje, hogy kis felbontású nyomtatást kényszerítsen ki, és egy 40 bites dokumentum figyelmen kívül hagyja Önt, mert ez a visszaminősítés is 128 bites vagy erősebb titkosítást igényel. Kódoljon egy „csak kis felbontású nyomtatás” szabályt egy 40 bites fájlba, és minden megjelenítő ugyanúgy teljes minőségben nyomtat
A mélyebb kérdés az, hogy ki kényszeríti ki ezeket a biteket, és a válasz: senki, akiben megbízhatna. Az engedélyek utasítások a szabványkövető olvasóknak, nem kriptográfiai korlátozások. A visszafejtő kulcs ugyanaz, akár engedélyezett a másolás, akár tiltott, tehát egy lezárt engedélykészlet csupán a becsületes megjelenítőket tartja becsületesnek. Az az olvasó, amely úgy dönt, hogy figyelmen kívül hagyja a biteket, semmilyen kriptográfiai akadállyal nem találkozik. Ha a kötelezettség a kinyerés megakadályozása, nem pedig a kedv elvétele, a fájlnak felhasználói jelszó kell, a munkafolyamatnak pedig köré épített, folyamatszintű felügyelet, és egy auditjelentésnek meg kell neveznie, melyik fájl melyik rendszer alá tartozik, ahelyett hogy zárnak tekintene egy engedélyjelzőt
Szabály beállítása, és annak bizonyítása, hogy meg is maradt
A titkosítás meglévő fájlokra alkalmazásához nem kell betölteni őket az objektumfába. Az EncryptFile egyetlen hívásban dolgozza fel a bemenetet kimenetté, az auditciklus pedig újranyitja az eredményt, hogy megerősítse, mi került a lemezre. A szállított titkosítási demó ugyanezt az írás-majd-visszaolvasás alakot követi:
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, // nyomtatás engedve; másolás/módosítás/jegyzet tiltva
0, 0, 0, 1)); // bővített készlet: csak teljes minőségű nyomtatás
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;
A dokumentumrétegen dolgozó csapatok ugyanezt a műveletet típusos halmazokkal kapják meg a bitcsomagolás helyett, ami sokkal kevesebb hunyorgással éli túl a kódellenőrzést:
if not Doc.Encrypt('owner-secret', 'user-secret', esAES256BitAcroX,
[ppCanPrint], [ppCanPrintFull]) then
raise Exception.Create('Encryption failed');
Bármelyik utat választja, a visszaolvasási lépés nem elhagyható szertartás. Épp azokat a telepítési hibákat kapja el, amelyek különben hónapokkal később, egy ügyfél gépén bukkannak fel: egy régi könyvtárbuild, amely némán visszaminősíti a kért erősséget; egy kimeneti útvonal, amelyre soha nem írt senki, mert a könyvtár csak olvasható volt; egy engedélyeket kódoló egész szám, amelynek argumentumai rossz sorrendben mentek be. Mindhárom átmegy egy helyi füstpróbán, és a terepen bukik el, márpedig a kimenet újranyitása mindegyiket olyan kivétellé alakítja, amelyet még abban a futásban lát, amely a fájlt létrehozta. A GetEncryptionFingerprint tömör értéket ad vissza, amelyet eltárolhat a feladatrekord mellé, így egy későbbi összehasonlítás anélkül is megmondja, hogy két kimenet azonos titkosítási beállítást hordoz-e, hogy bármelyiket újra kellene nyitni
Auditbeli téves riasztások, amelyekre érdemes kódot írni
Néhány minta megbízhatóan rossz következtetésre viszi a biztonsági szkennereket, és mindegyik abból ered, hogy egy többrészes kérdést igen-nem válasszá lapítanak. Az Identity titkosítószűrő a legtisztább példa. Van /Encrypt szótár, a fájl titkosítottként jelenti magát, a sztringek és a folyamok mégis változatlanul futnak át az Identity szűrőn, tehát a valódi tartalom nyílt szöveg. A megoldás az, hogy a StringFilterIdentity és a StreamFilterIdentity értékét elolvassuk, mielőtt bármit védettnek nyilvánítanánk
A metaadatok kettéválása finomabb eset. Az EncryptMetadata mindkét irányban eltérhet a dokumentum többi részétől: hagyhat olvasható XMP csomagot egy titkosított fájlban, vagy ritkábban fordítva. Az, hogy „a fájl titkosított”, semmit nem mond arról, hogy a metaadata is az-e, ami abban a pillanatban számít, amikor egy indexelő vagy egy útválasztási szabály a címért nyúl. A beágyazott fájlok egy harmadik tengelyt adnak: a PDF megenged egy külön titkosítószűrőt kifejezetten a mellékleteknek, tehát a mellékletek lehetnek az egyetlen titkosított rész egy egyébként nyitott dokumentumban, vagy az egyetlen nyílt szöveges rész egy titkosítottban. Rögzítse a három szűrő-hozzárendelést külön mezőként a sztringekre, a folyamokra és a beágyazott fájlokra, és egyik csapda sem tudja elkapni. Tároljon egyetlen logikai értéket, és a téves ítélet csak idő kérdése
A titkosítás eltávolítása, és a választás új fájlokhoz
Egy audit gyakran a védelem eltávolításáról szóló döntéssel zárul, és ott nem a gépezet az akadály. A DecryptFile(InputFileName, OutputFileName, Password) teljes betöltés nélkül ír visszafejtett másolatot, a betöltött dokumentumon hívott Decrypt pedig ugyanezt teszi a memóriában, ha a fájl már nyitva van. Mindkettőhöz érvényes jelszó kell; egyik sem kerüli meg a kriptográfiát. A valódi kapu nem a kód, hanem a szabályzat, ezért a befogadási szabályai mondják ki nyíltan, mikor engedélyezett az eltávolítás, és rögzítsék, melyik jelszóosztály hatalmazta fel rá, mert maga a technikai lépés semmilyen nyomot nem hagy
Az új kimenetre vonatkozó választás szűkebb, mint amennyit az öt Strength érték sugall. Használjon 4-es erősséget, vagyis AES-256 6-os revíziót, hacsak nem kell Acrobat X-nél régebbi megjelenítőkben is megnyitni a fájlokat. A 2-es erősség, az AES-128, a pragmatikus alsó határ egy öregedő, nem frissíthető megjelenítőparkhoz. A 0-s és 1-es RC4-lehetőség azért van ott, hogy történeti archívumokat olvasni és auditálni tudjon, nem azért, hogy bármi újat gyártson velük; ha egy 2026-os tervben nyúl értük, az annak a jele, hogy egy felsőbb követelmény elavult
A titkosítási állapot közvetlenül táplálja az aláírási döntéseket, hiszen egy dokumentumokat ellenőrző és aláíró munkapadnak ugyanarra a visszaolvasási fegyelemre van szüksége, amelyre ez az audit épül. Ezt a terepet a megfelelőségi és aláírási munkapadról szóló cikk járja be. Amikor egy köteg több ezer nagy dokumentumon futtatja az EncryptFile hívást, a nagy PDF-ek közvetlen hozzáférésű útmutatója mutatja meg, hogyan tartható lapos a memóriahasználat közben. A teljes titkosítási API-referencia a PDF Library for Delphi termékoldalán található