Műszaki cikk

PDF 2.0 AES-GCM titkosítás Delphiben: ISO/TS 32003

A PDFiumPas az ISO/TS 32003 titkosítást a SaveAsEncrypted függvényen keresztül írja: állítsd a Revision értéket erR7-re, és minden string és stream AES-256-tal védett GCM módban, ez a hitelesített rejtjelezés, amelyet a PDF 2.0 2023-ban kapott. Állítsd be az EnableIntegrityProtection értéket is, és a dokumentum egy önálló PDF MAC tokent is hordoz, amelyet a ValidatePdfMac ellenőriz az olvasási oldalon

Ez két különböző védelem, amelyeket az emberek rendszeresen összekevernek. A GCM minden titkosított értéket hitelesít. A MAC a dokumentumot egészében hitelesíti. Mindkettőre szükséged van, különböző okokból

Mit ad hozzá a GCM, amit a CBC soha nem nyújtott?

A titkosított szöveg hitelesítését. Az AES-256 CBC módban, az ISO 32000-2-ben szereplő AESV3 séma, bizalmasan tartja a tartalmat, és semmit sem mond arról, hogy módosítás nélkül érkezett-e. A CBC specifikus, jól ismert módokon képlékeny: egy támadó, aki bitet tud forgatni a titkosított szövegben, kiszámítható változásokat idéz elő a következő blokk nyílt szövegében, és semmi a formátumban ezt nem veszi észre

A GCM ezt lezárja. Minden titkosított érték hordoz egy 16 byte-os hitelesítési taget, teljes egészében szerializálva, ahogy az ISO/TS 32003 megköveteli, és a dekódolás meghiúsul ahelyett, hogy módosított nyílt szöveget adna vissza, ha a tag nem egyezik. PDF-fogalmakkal élve, egy manipulált string vagy stream egy AESV4 dokumentumban kemény hiba a felhasználás pontján, nem egy furcsa érték, amely átterjed az alkalmazásodba. Az Encrypt szótár ezt a /CFM /AESV4 és a V 6 / R 7 jelöléssel jelzi, egy extensions bejegyzés mellett, amely /ExtensionLevel 32003 és /ExtensionRevision (:2023) értékeket deklarál

Három verzió, három ökoszisztéma

A TPdfEncryptionRevision az erR5, az erR6 és az erR7 értékeket kínálja, és a választás inkább kompatibilitási, mint kriptográfiai döntés. Az R5 az eredeti AES-256 séma, amelyet PDF 1.7 kiterjesztésként publikáltak, egyetlen SHA-256 jelszó-hash-sel, és lényegében bármi megnyitja az elmúlt tizenöt évből. Az R6 az ISO 32000-2-ben szabványosított megerősített kulcsszármaztatás, amely a 2.B algoritmus iteráló SHA-256/384/512 konstrukcióját használja, és ez az, amit egy jelenlegi PDF 2.0 vagy PDF/A-4 munkafolyamat elvár. Az R7 az ISO/TS 32003, amely ugyanazt a 2.B származtatást használja AES-GCM rejtjelezéssel

Az olvasói támogatás pontosan ebben a sorrendben halad, és az R7 támogatása még mindig gyenge a jelenlegi mainstream megjelenítőkön kívül. Ez ugyanaz a kompromisszum, amely bármely PDF 2.0 funkciót irányít: a legújabb opció a legjobb mérnöki munka és a legszűkebb közönség. Döntsd el az alapján, hogy kinek kell megnyitnia a fájlt, és ha a válasz az, hogy „egy nyilvántartási rendszer, amelyet senki sem frissített 2019 óta”, akkor a válasz az R5, függetlenül attól, mit preferálna a biztonsági szabályzat

uses
  PDFium, FPdfEncrypt;

var
  Pdf: TPdf;
  Opts: TPdfEncryptOptions;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'quarterly-report.pdf';
    Pdf.LoadDocument;

    Opts := TPdfEncryptOptions.Default;
    Opts.UserPassword := 'open-secret';
    Opts.OwnerPassword := 'admin-secret';
    Opts.EncryptMetadata := True;
    Opts.Revision := erR7;                    // ISO/TS 32003 AESV4-GCM
    Opts.EnableIntegrityProtection := True;   // önálló PDF MAC token

    if not Pdf.SaveAsEncrypted('quarterly-report.enc.pdf', Opts) then
      raise Exception.Create('Encrypted save failed');
  finally
    Pdf.Free;
  end;
end;

Miért kell dokumentum-MAC egy hitelesített rejtjelezés tetejére?

Mert a GCM tagek az értékeket védik, nem az értékek elrendezését. Egy AESV4 dokumentumban minden string és stream egyénileg hitelesített, ám a kereszthivatkozás-tábla, az objektumszámozás és a trailer szerkezet, nem titkosított tartalom. Egy támadó nem tud stream-et hamisítani, de önmagában a rejtjelezésben semmi sem akadályozza meg abban, hogy átrendezze, mely objektumokra mutat a dokumentum, vagy objektumokat illesszen be ugyanazon fájl egy korábbi verziójából

Az önálló PDF MAC token ezt a réteget kezeli. A PDFiumPas a fájl titkosítási kulcsából származtatja, egy dedikált, 32 byte-os, az Encrypt szótárban rögzített /KDFSalt segítségével, így a jelszó birtoklása az, ami lehetővé teszi egy olvasónak a token megerősítését. Az eredmény egyetlen válasz egyetlen kérdésre: ez a dokumentum, egészében, ugyanaz a dokumentum, amelyet írtak

var
  Pdf: TPdf;
  Mac: TPdfMacValidationResult;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.Password := 'open-secret';
    Pdf.FileName := 'quarterly-report.enc.pdf';
    Pdf.LoadDocument;

    Mac := Pdf.ValidatePdfMac('open-secret');
    case Mac.Status of
      pmvsValid:       ProcessDocument(Pdf);
      pmvsNotPresent:  ProcessWithWarning(Pdf);       // nincs token ebben a fájlban
      pmvsInvalid:     Quarantine(Mac.MessageText);   // manipulált vagy csonka
      pmvsUnsupported: RouteForManualReview(Mac.MessageText);
    end;
  finally
    Pdf.Free;
  end;
end;

A négy állapotérték négy különböző választ igényel, és ha booleanná zsugorítod őket, elveszik a megkülönböztetés, amely számít. A pmvsNotPresent azt jelenti, hogy a fájlnak egyszerűen nincs tokenje, ami szinte minden 2024 előtt írt titkosított PDF-et leír, és semminek sem bizonyítéka. A pmvsInvalid azt jelenti, hogy egy token jelen van, de nem igazolható, ami valódi eredmény, és le kell állítania a feldolgozást. A pmvsUnsupported azt jelenti, hogy a token olyan alakban létezik, amelyet ez a build nem implementál, ami kompatibilitási hiányosság, nem támadás. Ha a „nincs jelen” állapotot „érvénytelenként” kezeled, az első napon karanténba tennéd a teljes archívumodat

Amit a titkosítás továbbra sem tesz meg

A jogosultsági jelzők azok maradnak, amik mindig is voltak: egy kérés a megfelelő szoftver felé, nem egy vezérlés. Az ISO 32000-1 22. táblázatából származó /P bitek, amelyek megtiltják a nyomtatást vagy a kinyerést, a jól viselkedő megjelenítők tiszteletben tartják, és minden más figyelmen kívül hagyja, és bárki, aki birtokolja a felhasználói jelszót, már birtokolja a dekódolt tartalmat is. A titkosítás a határ; a jogosultságok a szándékot írják le azon belül

Két üzemeltetési részlet érdemes megtervezni. Először: a titkosítás és a későbbi módosítás kölcsönhatásba lép: egy inkrementális frissítés hozzáfűzése egy titkosított dokumentumhoz saját szabályokkal rendelkezik, amelyeket a titkosított PDF-ek inkrementális frissítései című cikk tárgyal, és egy MAC token egy dokumentumszintű kijelentés, amelyet egy figyelmetlen hozzáfűzés érvénytelenít. Másodszor: a GCM konstrukció determinisztikus IV-számlálót használ, és a PDFiumPas kivételt dob ahelyett, hogy újrafelhasználna egy számlálóértéket, ha ez a tér valaha kimerülne, mert a nonce újrafelhasználása GCM-ben katasztrofális módon, amit egy csendes túlcsordulás elrejtene

A három verzió közötti választás a gyakorlatban

Írd le, ki nyitja meg a fájlt, aztán válassz. Belső terjesztéshez, ahol minden olvasó a te irányításod alatt álló, aktuális megjelenítő, az R7 integritásvédelemmel a legerősebb elérhető opció, és nincs ok arra, hogy ne ezt használd. A szervezetet elhagyó dokumentumoknál az R6 a védhető alapértelmezés: ez az ISO 32000-2-ben van szabványosítva, nem egy rá épülő technikai specifikációban, és a támogatottsága széles körű. Archívumokhoz és örökölt fogyasztókhoz az R5 az egyetlen választás, amely megbízhatóan megnyílik, és érdemes feljegyezned, hogy miért, ugyanott, ahol a megőrzési szabályzatod többi részét rögzíted

Bármelyiket is választod, ellenőrizd a kimenetet ahelyett, hogy megbíznál abban, hogy a hívás sikeres volt. Nyisd meg újra a titkosított fájlt, ellenőrizd a ValidatePdfMac értéket, és erősítsd meg, hogy a deklarált verzió az, amit vársz, a pontos PDF-verzió megfelelőség című cikkben leírt verzió-megfelelőségi ellenőrzésekkel. Egy szélesebb körű befogadási ellenőrzőlista nem megbízható dokumentumokhoz a PDF biztonsági kockázatok auditálása című cikkben található

A PDFiumPas egy Delphi és Lazarus komponens a PDFium motor köré építve, a PDF 2.0 titkosítási verem natívan Pascalban van implementálva, így az AES-256, a GCM és a MAC token nem igényel külső titkosítási DLL-t. A titkosítási API a PDFium Delphi komponens oldalán van dokumentálva