PDFiumPas scrie criptare ISO/TS 32003 prin SaveAsEncrypted: setează Revision la erR7 și fiecare string și stream este protejat cu AES-256 în modul GCM, cifrul autentificat pe care PDF 2.0 l-a primit în 2023. Setează și EnableIntegrityProtection, iar documentul poartă și un token PDF MAC independent, pe care ValidatePdfMac îl verifică la citire
Acestea sunt două protecții diferite pe care oamenii le confundă frecvent. GCM autentifică fiecare valoare criptată. MAC-ul autentifică documentul ca întreg. Le vrei pe amândouă, din motive diferite
Ce adaugă GCM față de ce nu a oferit niciodată CBC?
Autentificarea textului cifrat. AES-256 în modul CBC, schema AESV3 din ISO 32000-2, păstrează conținutul confidențial și nu spune nimic despre dacă a ajuns nemodificat. CBC este maleabil în moduri specifice, bine studiate: un atacator care poate inversa biți în textul cifrat produce schimbări previzibile în textul simplu al blocului următor, iar nimic din format nu observă
GCM închide acea breșă. Fiecare valoare criptată poartă un tag de autentificare de 16 bytes, serializat complet așa cum cere ISO/TS 32003, iar decriptarea eșuează în loc să returneze text simplu alterat atunci când tag-ul nu se potrivește. În termeni PDF, un string sau stream modificat într-un document AESV4 este o eroare fermă chiar la punctul de utilizare, nu o valoare stranie care se propagă în aplicația ta. Dicționarul Encrypt marchează asta cu /CFM /AESV4 și V 6 / R 7, alături de o intrare de extensie care declară /ExtensionLevel 32003 și /ExtensionRevision (:2023)
Trei revizii, trei ecosisteme
TPdfEncryptionRevision oferă erR5, erR6 și erR7, iar alegerea este mai degrabă o decizie de compatibilitate decât una criptografică. R5 este schema originală AES-256 publicată ca extensie PDF 1.7, cu un singur hash de parolă SHA-256, și se deschide practic în orice din ultimii cincisprezece ani. R6 este derivarea de cheie întărită standardizată în ISO 32000-2, folosind construcția iterativă SHA-256/384/512 a algoritmului 2.B, și este ce așteaptă un flux de lucru curent PDF 2.0 sau PDF/A-4. R7 este ISO/TS 32003, folosind aceeași derivare 2.B, dar cu AES-GCM ca cifru
Suportul cititoarelor urmează exact această ordine, iar suportul pentru R7 este încă subțire în afara viewerelor mainstream curente. Acesta este același compromis care guvernează orice funcționalitate PDF 2.0: opțiunea cea mai nouă este cea mai bună din punct de vedere inginer și are cea mai îngustă audiență. Decide după cine trebuie să deschidă fișierul, iar dacă răspunsul este „un sistem de arhivare pe care nimeni nu l-a actualizat din 2019”, răspunsul este R5 indiferent de ce preferă politica de securitate
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; // token PDF MAC independent
if not Pdf.SaveAsEncrypted('quarterly-report.enc.pdf', Opts) then
raise Exception.Create('Encrypted save failed');
finally
Pdf.Free;
end;
end;
De ce un MAC de document peste un cifru deja autentificat?
Pentru că tag-urile GCM protejează valorile, nu aranjamentul valorilor. Fiecare string și stream dintr-un document AESV4 este autentificat individual, totuși tabela cross-reference, numerotarea obiectelor și trailer-ul sunt structură, nu conținut criptat. Un atacator nu poate falsifica un stream, dar nimic din cifru, luat separat, nu îl oprește să rearanjeze spre ce obiecte indică documentul, sau să lipească obiecte dintr-o revizie anterioară a aceluiași fișier
Token-ul PDF MAC independent adresează acel strat. PDFiumPas îl derivă din cheia de criptare a fișierului cu un /KDFSalt dedicat de 32 de bytes, înregistrat în dicționarul Encrypt, astfel încât deținerea parolei este ce permite unui cititor să confirme token-ul. Rezultatul este un singur răspuns la o singură întrebare: este acest document, ca întreg, documentul care a fost scris
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); // niciun token în acest fișier
pmvsInvalid: Quarantine(Mac.MessageText); // modificat sau trunchiat
pmvsUnsupported: RouteForManualReview(Mac.MessageText);
end;
finally
Pdf.Free;
end;
end;
Cele patru valori de stare cer patru răspunsuri diferite, iar reducerea lor la un boolean pierde distincția care contează. pmvsNotPresent înseamnă că fișierul pur și simplu nu are token, ceea ce descrie aproape orice PDF criptat scris înainte de 2024 și nu este dovada a nimic. pmvsInvalid înseamnă că un token este prezent și nu se verifică, ceea ce este o constatare autentică și ar trebui să oprească procesarea. pmvsUnsupported înseamnă că token-ul există într-o formă pe care această versiune nu o implementează, ceea ce este un gol de compatibilitate, nu un atac. Tratarea „absent” ca „invalid” ți-ar pune în carantină întregul arhivat de la prima zi
Ce încă nu face criptarea
Flag-urile de permisiune rămân ce au fost mereu: o cerere către software-ul conform, nu un control. Biții /P din tabelul 22 al ISO 32000-1 care interzic tipărirea sau extragerea sunt respectați de viewerele bine-crescute și ignorați de tot restul, iar oricine deține parola de utilizator deține deja conținutul decriptat. Criptarea este granița; permisiunile descriu intenția din interiorul ei
Două detalii operaționale merită planificate. Primul, criptarea și modificarea ulterioară interacționează: adăugarea unei actualizări incrementale la un document criptat are propriile reguli, acoperite în actualizări incrementale pe PDF-uri criptate, iar un token MAC este o declarație la nivel de document pe care o adăugare neglijentă o va invalida. Al doilea, construcția GCM folosește un contor IV determinist, iar PDFiumPas ridică o excepție în loc să reutilizeze o valoare de contor dacă acel spațiu ar fi vreodată epuizat, pentru că reutilizarea unui nonce în GCM este catastrofală într-un mod pe care o depășire silențioasă l-ar ascunde
Alegerea între cele trei revizii în practică
Notează cine deschide fișierul, apoi alege. Pentru distribuție internă unde fiecare cititor este un viewer curent sub controlul tău, R7 cu protecție de integritate este cea mai puternică opțiune disponibilă și nu există niciun motiv să nu o folosești. Pentru documentele care părăsesc organizația, R6 este valoarea implicită apărabilă: este standardizată în ISO 32000-2, nu într-o specificație tehnică deasupra ei, iar suportul este larg. Pentru arhive și consumatori vechi, R5 este singura alegere care se deschide fiabil, și ar trebui să notezi de ce în același loc unde notezi restul politicii tale de retenție
Oricare ai alege, verifică rezultatul în loc să te încrezi că apelul a reușit. Redeschide fișierul criptat, verifică ValidatePdfMac, și confirmă că versiunea declarată este cea așteptată, folosind verificările de conformitate a versiunii din conformitatea exactă cu versiunea PDF. O listă de verificare mai largă pentru documentele nesigure este în auditarea riscurilor de securitate PDF
PDFiumPas este o componentă Delphi și Lazarus în jurul motorului PDFium, cu stiva de criptare PDF 2.0 implementată nativ în Pascal, astfel încât AES-256, GCM și token-ul MAC nu au nevoie de niciun DLL extern de criptografie. API-ul de criptare este documentat pe pagina componentei PDFium Delphi