Příznak oprávnění není bezpečnostní mechanismus. Bit, který říká „kopírování zakázáno“, sídlí v témže slovníku /Encrypt jako kryptografie, což mu propůjčuje nádech vymahatelnosti, jakou nemá, a ve chvíli, kdy obojí považujete za jednu věc, začne váš audit produkovat špatné odpovědi. Otázka, kterou má smysl PDF položit, nezní „je zašifrované?“. Je konkrétnější a těžší: který algoritmus, která revize bezpečnostního handleru, které ze dvou hesel bylo nastaveno, které bity oprávnění si soubor nárokuje a kterých částí souboru se šifrování skutečně dotýká. Soubor může být formálně zašifrovaný a prakticky otevřený. Může odmítat být přečten, a přitom nechávat svá metadata v otevřeném textu. Může zamykat tisk příznakem, který každý prohlížeč může beztrestně ignorovat. Auditovat PDF znamená vyřešit všechny tyto věci zvlášť a PDF Library for Delphi, engine PDF od losLab pro Delphi a C++Builder, zpřístupňuje každou z nich jak přes ploché API s celočíselnými handly, tak přes typovanou vrstvu tříd
Co slovník /Encrypt ve skutečnosti zaznamenává
ISO 32000-1 §7.6 definuje zabezpečení dokumentu skrze hrstku položek slovníku a PDF Library for Delphi je jednu ku jedné zrcadlí v záznamu TPDFEncryption. Verze filtru V a revize R volí rodinu algoritmu. Length nese velikost klíče. Bity oprávnění sedí v P, validační řetězce hesla vlastníka a uživatele v O a U (u AES-256 přibývají OE a UE), vedle nich jede příznak EncryptMetadata a další tři pole pojmenovávají šifrovací filtry použité postupně na řetězce, streamy a vložené soubory
Cena tohoto záznamu spočívá v tom, že za vás nic neinterpretuje. Vrátí surový slovník a závěry nechá na vás, což je přesně to, co audit potřebuje. Případ „otevřený text uvnitř zašifrovaného“ se projeví v StringFilterIdentity a StreamFilterIdentity: je-li kterýkoli z nich true, procházejí odpovídající data filtrem Identity beze změny, ať už zašifrovaný stav dokumentu hlásí cokoli. Skener, který se zastaví u konstatování „slovník /Encrypt je přítomen“, označí takový soubor za chráněný, zatímco jeho řetězce a streamy leží nezakrytě. Tatáž nuance vládne metadatům. Je-li EncryptMetadata false, zůstává balíček XMP čitelný pro každý indexer, zatímco obsah stránek nikoli, což je dobré vědět v okamžiku, kdy se vaše směrovací pravidla opírají o pole s titulem nebo autorem
Krátká bezpečnostní sonda pomocí plochého API
Pro většinu pipeline zodpoví každodenní otázky čtyři plochá volání. LoadFromFile vrací při úspěchu 1 a jakmile je dokument otevřený, hlásí inspektory šifrování stav vůči jeho dešifrované podobě:
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); // dešifrováno / zašifrováno / neznámo
Writeln('algorithm : ', PDF.EncryptionAlgorithm); // rodina RC4 vs AES
Writeln('strength : ', PDF.EncryptionStrength); // třída délky klíče
Writeln('owner pw? : ', PDF.CheckPassword(CandidatePassword));
finally
PDF.Free;
end;
end;
CheckPassword je důležitější, než jeho jednořádková hlavička napovídá. PDF definuje dvě hesla s nestejnou mocí. Uživatelské heslo je nutné vůbec k otevření souboru. Heslo vlastníka uděluje plná práva a přebíjí každý bit oprávnění. Bajty na disku jsou v obou případech totožné, ale relace otevřená pod heslem vlastníka umí věci, které relace s uživatelským heslem neumí, takže audit, jenž nezaznamená, který údaj byl předložen, zaznamenává jen polovinu pravdy. Vrstva tříd tento rozdíl umožňuje dotazovat. TPDFDocument.HasUserPassword a HasOwnerPassword hlásí, co soubor vyžaduje, zatímco IsUserPassword a IsOwnerPassword hlásí, které heslo aktuální relaci skutečně otevřelo. Tento fakt logujte. Samotné hodnoty hesel nelogujte nikdy
Žebříček Strength, kde „AES-256“ znamená dvě věci
Ploché funkce Encrypt a EncryptFile berou celočíselný parametr Strength s pěti smysluplnými hodnotami: 0 pro 40bitové RC4, 1 pro 128bitové RC4, 2 pro 128bitové AES čitelné od Acrobatu 7, 3 pro 256bitové AES uvedené s Acrobatem 9 a 4 pro 256bitové AES vyžadované Acrobatem X a novějším
Zajímavé je, že 3 i 4 jsou obě označované jako AES-256 a nejde o totéž schéma. Strength 3 odpovídá revizi 5 bezpečnostního handleru, což je přechodný návrh, který Acrobat 9 vypustil a ISO nikdy nepřevzalo. Strength 4 odpovídá revizi 6, jejíž funkce pro odvození klíče byla zpevněna a standardizována v ISO 32000-2. U dokumentu, který vytváříte dnes, není důvod volit 3 místo 4. Pro audit je ten rozdíl rozhodující: politiku znějící „AES-256 podle ISO 32000-2“ splňuje jedině R6 a soubor s R5, který si říká AES-256, takové politice nevyhoví, přestože naivní kontrolou síly projde. Vrstva tříd obě varianty rozlišuje názvem, esAES256Bit pro R5 proti esAES256BitAcroX pro R6, a vlastnost EncryptionAcroX odpoví na otázku po revizi jedinou logickou hodnotou
Bity oprávnění a jejich drobné písmo o délce klíče
EncodePermissions zabalí osm příznaků do celého čísla, které Encrypt a EncryptFile očekávají. Tisk, kopírování, změny a přidávání poznámek tvoří základní sadu; vyplňování polí, kopírování pro zpřístupnění, sestavování a tisk v plné kvalitě tvoří sadu rozšířenou. Drobné písmo, které ukázka šifrování dodávaná s knihovnou uvádí zcela otevřeně, zní, že se ta rozšířená čtveřice uplatní jen při síle 128 bitů a výš. Příznak tisku v plné kvalitě spadá pod totéž pravidlo: zrušte jej, abyste vynutili tisk v nízkém rozlišení, a 40bitový dokument vás bude ignorovat, protože i toto omezení vyžaduje 128bitové nebo silnější šifrování. Zakódujte politiku „pouze tisk v nízkém rozlišení“ do 40bitového souboru a každý prohlížeč jej stejně vytiskne v plné kvalitě
Hlubší otázka zní, kdo kterýkoli z těch bitů vymáhá, a odpověď je, že nikdo, komu byste mohli věřit. Oprávnění jsou pokyny pro čtečky dodržující specifikaci, nikoli kryptografická omezení. Dešifrovací klíč je totožný, ať už je kopírování povolené, či zakázané, takže zamčená sada oprávnění udrží poctivé jen ty prohlížeče, které poctivé už jsou. Čtečka, jež se rozhodne bity ignorovat, nenarazí na žádnou kryptografickou překážku. Je-li povinností extrakci znemožnit, a ne od ní jen odrazovat, potřebuje soubor uživatelské heslo a pracovní postup potřebuje procesní kontroly kolem něj; auditní zpráva by pak měla u každého souboru pojmenovat, pod který z těch dvou režimů skutečně spadá, místo aby brala příznak oprávnění jako zámek
Nastavení politiky a důkaz, že se uchytila
Nasazení šifrování na existující soubory nevyžaduje jejich načtení do objektového stromu. EncryptFile zpracuje vstup na výstup jediným voláním a auditní smyčka výsledek znovu otevře, aby potvrdila, co skutečně dosedlo na disk. Dodávaná ukázka šifrování má stejný tvar zapiš-a-přečti-zpět:
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, // tisk povolen; kopírování/změny/poznámky zakázány
0, 0, 0, 1)); // rozšířená sada: pouze tisk v plné kvalitě
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;
Týmy pracující na úrovni dokumentu dostanou tutéž operaci s typovanými množinami namísto balení bitů, což přežije revizi kódu s podstatně menším mhouřením očí:
if not Doc.Encrypt('owner-secret', 'user-secret', esAES256BitAcroX,
[ppCanPrint], [ppCanPrintFull]) then
raise Exception.Create('Encryption failed');
Tak či onak není krok se zpětným přečtením volitelný obřad. Odchytí nasazovací chyby, které by jinak vyplavaly o měsíce později na zákaznickém stroji: staré sestavení knihovny, které tiše sníží požadovanou sílu, výstupní cestu, do níž se nikdy nezapsalo, protože adresář byl jen pro čtení, celé číslo s oprávněními, jehož argumenty šly ve špatném pořadí. Všechny tři projdou místním kouřovým testem a selžou v terénu, a znovuotevření výstupu z každé z nich udělá výjimku, kterou uvidíte během běhu, jenž ten soubor vytvořil. GetEncryptionFingerprint vrací kompaktní hodnotu, kterou můžete uložit spolu se záznamem úlohy, takže pozdější porovnání dokáže říct, zda dva výstupy sdílejí tutéž konfiguraci šifrování, aniž by bylo nutné kterýkoli z nich otevírat
Falešné poplachy auditu, na které se vyplatí myslet v kódu
Několik vzorců spolehlivě dotlačí bezpečnostní skenery ke špatnému závěru a každý z nich pramení ze zploštění vícedílné otázky na odpověď ano/ne. Šifrovací filtr Identity je nejčistší příklad. Slovník /Encrypt je přítomen, soubor se hlásí jako zašifrovaný, a přitom řetězce i streamy procházejí filtrem Identity beze změny, takže skutečný obsah je v otevřeném textu. Nápravou je přečíst StringFilterIdentity a StreamFilterIdentity dřív, než cokoli prohlásíte za chráněné
Rozdělení metadat je jemnější. EncryptMetadata se může se zbytkem dokumentu rozejít v obou směrech a zanechat zašifrovaný soubor s čitelným balíčkem XMP nebo, méně často, naopak. Věta „soubor je zašifrovaný“ neříká nic o tom, zda jsou zašifrovaná i jeho metadata, což začne být důležité ve chvíli, kdy po titulu sáhne indexer nebo směrovací pravidlo. Vložené soubory přidávají třetí osu: PDF povoluje vyhrazený šifrovací filtr jen pro přílohy, takže přílohy mohou být jedinou zašifrovanou částí jinak otevřeného dokumentu, nebo jedinou otevřenou částí dokumentu zašifrovaného. Zachyťte přiřazení všech tří filtrů jako samostatná pole pro řetězce, streamy a vložené soubory a žádná z těchto pastí vás nedostane. Uložte jedinou logickou hodnotu a špatný závěr je jen otázkou času
Odstranění šifrování a jeho volba pro nové soubory
Audit často končí rozhodnutím ochranu odstranit a mechanika v tom není překážkou. DecryptFile(InputFileName, OutputFileName, Password) zapíše dešifrovanou kopii bez plného načtení a metoda Decrypt nad načteným dokumentem udělá totéž v paměti, jakmile je soubor už otevřený. Obě vyžadují platné heslo; ani jedna kryptografii neobchází. Skutečnou branou je politika, ne kód, takže ať vaše příjmová pravidla jasně říkají, kdy je odstranění povolené, a ať se zaznamenává třída hesla, které to autorizovalo, protože samotný technický krok po sobě žádnou stopu nenechává
Volba pro nový výstup je užší, než pět hodnot Strength naznačuje. Používejte Strength 4, tedy AES-256 revize 6, pokud nemusíte otevírat soubory v prohlížečích starších než Acrobat X. Strength 2, tedy AES-128, je pragmatické dno pro stárnoucí flotilu prohlížečů, kterou nelze povýšit. Varianty RC4 na 0 a 1 tu jsou proto, abyste mohli číst a auditovat historické archivy, nikoli proto, abyste s nimi vytvářeli cokoli nového; sáhnout po nich v návrhu z roku 2026 je známkou, že někde nahoře uvázl zastaralý požadavek
Stav šifrování vstupuje přímo do rozhodování o podpisu, protože pracovní prostředí, které dokumenty validuje a podepisuje, potřebuje tutéž disciplínu zpětného čtení, o niž se opírá tento audit. Tomu se věnuje článek o pracovním prostředí pro shodu a podepisování. Když dávka aplikuje EncryptFile na tisíce rozsáhlých dokumentů, ukazuje průvodce přímým přístupem k velkým PDF, jak přitom udržet spotřebu paměti plochou. Kompletní referenční příručka šifrovacího API žije na produktové stránce PDF Library for Delphi