Technical Article

Revizija PDF šifriranja i dopuštenja u Delphiju s PDFlibPas-om

Zastavica dopuštenja nije sigurnosni mehanizam. Bit koji kaže "zabranjeno kopiranje" živi unutar istog rječnika /Encrypt kao i kriptografija, što mu daje privid provođenja koji zapravo nema, i u trenutku kada to dvoje tretirate kao jednu stvar, vaša revizija počinje davati pogrešne odgovore. Jedino pitanje koje vrijedi postaviti za PDF nije "je li šifriran." Ono je specifičnije i teže: koji algoritam, koja revizija sigurnosnog rukovatelja, koja od dvije lozinke je postavljena, koji se bitovi dopuštenja traže i koje dijelove datoteke šifriranje stvarno dotiče. Datoteka može biti formalno šifrirana, a praktički otvorena. Može odbiti čitanje, a ostaviti svoje metapodatke u običnom tekstu. Može zaključati ispis u zastavici koju bilo koji preglednik može slobodno zanemariti. Revizija PDF-a znači rješavanje svakog od tih aspekata zasebno, a PDFlibPas, losLab-ov PDF mehanizam za Delphi i C++Builder, izlaže svaki od njih i kroz ravni API s cjelobrojnim ručkama i kroz tipizirani klasni sloj.

Što rječnik /Encrypt zapravo bilježi

ISO 32000-1 §7.6 definira sigurnost dokumenta kroz nekoliko unosa u rječniku, a PDFlibPas ih preslikava jedan na jedan u zapis TPDFEncryption. Verzija filtra V i revizija R odabiru obitelj algoritama. Length nosi veličinu ključa. Bitovi dopuštenja nalaze se u P, nizovi za provjeru vlasničke i korisničke lozinke u O i U (uz dodane OE i UE za AES-256), zastavica EncryptMetadata ide uz to, a još tri polja imenuju filtre šifriranja primijenjene na nizove znakova, tokove i ugrađene datoteke.

Vrijednost ovog zapisa je u tome što on ne tumači ništa umjesto vas. Vraća vam sirovi rječnik i dopušta vam da sami donesete zaključke, što je upravo ono što revizija treba. Slučaj običnog teksta unutar šifriranog dokumenta pojavljuje se u StringFilterIdentity i StreamFilterIdentity: kada je bilo koje od njih istinito, odgovarajući podaci prolaze kroz filtar Identity netaknuti, bez obzira na to što izvješćuje status šifriranja dokumenta. Skener koji se zaustavlja na "rječnik /Encrypt je prisutan" nazvat će takvu datoteku zaštićenom iako su njezini nizovi i tokovi u čistom tekstu. Ista nijansa upravlja metapodacima. Kada je EncryptMetadata lažno, XMP paket ostaje čitljiv bilo kojem indeksatoru dok sadržaj stranice nije, što je važno znati čim se vaša pravila usmjeravanja oslanjaju na polje naslova ili autora.

Kratka sigurnosna provjera s ravnim API-jem

Za većinu cjevovoda, četiri ravna poziva odgovaraju na svakodnevna pitanja. LoadFromFile vraća 1 u slučaju uspjeha, a nakon što je dokument otvoren, inspektori šifriranja izvješćuju u odnosu na njegovo dešifrirano stanje:

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);     // decrypted / encrypted / unknown
    Writeln('algorithm : ', PDF.EncryptionAlgorithm);  // RC4 vs AES family
    Writeln('strength  : ', PDF.EncryptionStrength);   // key length class
    Writeln('owner pw? : ', PDF.CheckPassword(CandidatePassword));
  finally
    PDF.Free;
  end;
end;

Ljestvica snage, gdje "AES-256" means two things

Ravne funkcije Encrypt i EncryptFile primaju cjelobrojnu snagu (Strength) s pet značajnih vrijednosti: 0 za 40-bitni RC4, 1 za 128-bitni RC4, 2 za 128-bitni AES čitljiv od Acrobata 7, 3 za 256-bitni AES kako je uveden s Acrobatom 9 i 4 za 256-bitni AES kako zahtijeva Acrobat X i noviji.

Zanimljiv dio je da su 3 i 4 oba označena kao AES-256, a nisu ista shema. Snaga 3 preslikava se na reviziju 5 sigurnosnog rukovatelja, privremeni dizajn koji je isporučio Acrobat 9, a ISO ga nikada nije usvojio. Snaga 4 preslikava se na reviziju 6, čija je funkcija izvođenja ključa ojačana i standardizirana u ISO 32000-2. Za dokument koji stvarate danas nema razloga odabrati 3 umjesto 4. Za reviziju je taj jaz odlučujući: pravilo koje glasi "AES-256 prema ISO 32000-2" ispunjava samo R6, a R5 datoteka koja sebe naziva AES-256 ne ispunjava to pravilo iako prolazi jednostavnu provjeru snage. Klasni sloj drži to dvoje razdvojenim po nazivu, esAES256Bit za R5 naspram esAES256BitAcroX za R6, a svojstvo EncryptionAcroX odgovara na pitanje o reviziji jednim booleanom.

Bitovi dopuštenja i sitni tisak o duljini ključa

Metoda EncodePermissions pakira osam zastavica u cijeli broj koji očekuju Encrypt i EncryptFile. Ispis, kopiranje, izmjena i dodavanje bilješki čine osnovni skup; popunjavanje polja, kopiranje radi pristupačnosti, sastavljanje i ispis u punoj kvaliteti čine prošireni skup. Sitni tisak, koji demonstracija šifriranja same knjižnice izravno navodi, jest da proširena četiri stupaju na snagu samo pri snazi od 128 bita i više. Zastavica za ispis u punoj kvaliteti potpada pod isto pravilo: očistite je kako biste prisilili ispis niske razlučivosti i 40-bitni dokument će vas zanemariti, cuz to smanjenje kvalitete također zahtijeva 128-bitno ili jače šifriranje. Kodirajte pravilo "samo ispis niske razlučivosti" u 40-bitnu datoteku i svaki će je preglednik ionako ispisati u punoj kvaliteti.

Dublje pitanje je tko provodi bilo koji od ovih bitova, a odgovor je – nitko kome možete vjerovati. Dopuštenja su upute usklađenim čitačima, a ne kriptografska ograničenja. Ključ za dešifriranje je identičan bez obzira na to je li kopiranje dopušteno ili zabranjeno, pa zaključani skup dopuštenja drži poštene preglednike poštenima. Čitač koji odluči zanemariti te bitove ne suočava se s nikakvom kriptografskom preprekom. Ako je obveza spriječiti ekstrakciju, a ne samo obeshrabriti je, datoteka treba korisničku lozinku, a tijek rada treba kontrole na razini procesa oko nje, a revizijsko izvješće trebalo bi imenovati pod kojim je režimom svaka datoteka zapravo, umjesto da zastavicu dopuštenja tretira kao bravu.

Postavljanje pravila i dokazivanje da su primijenjena

Primjena šifriranja na postojeće datoteke ne zahtijeva njihovo učitavanje u stablo objekata. EncryptFile obrađuje ulaz u izlaz u jednom pozivu, a revizijska petlja ponovno otvara rezultat kako bi potvrdila što je završilo na disku. Isporučena demonstracija šifriranja slijedi isti oblik pisanja i ponovnog čitanja:

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,    // print allowed; copy/change/notes denied
                            0, 0, 0, 1));  // extended set: full-quality print only
    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;

Timovi koji rade na razini dokumenata dobivaju istu operaciju s tipiziranim skupovima umjesto pakiranja bitova, što prolazi kroz pregled koda s puno manje napora:

if not Doc.Encrypt('owner-secret', 'user-secret', esAES256BitAcroX,
  [ppCanPrint], [ppCanPrintFull]) then
  raise Exception.Create('Encryption failed');

U svakom slučaju, korak ponovnog čitanja nije neobavezna ceremonija. On hvata greške u implementaciji koje se inače pojavljuju mjesecima kasnije na stroju korisnika: staru verziju knjižnice koja tiho smanjuje traženu snagu, izlaznu stazu koja nikada nije zapisana jer je direktorij bio samo za čitanje, cijeli broj dopuštenja čiji su argumenti otišli pogrešnim redoslijedom. Sva tri prolaze lokalni test i ne uspijevaju na terenu, a ponovno otvaranje izlaza pretvara svaki od njih u iznimku koju vidite tijekom pokretanja koje je stvorilo datoteku. GetEncryptionFingerprint ova metoda vraća kompaktnu vrijednost koju možete pohraniti sa zapisom posla, tako da kasnija usporedba može reći dijele li dva izlaza istu konfiguraciju šifriranja bez ponovnog otvaranja bilo kojeg od njih.

Lažno pozitivni rezultati revizije koje vrijedi kodirati

Nekoliko obrazaca pouzdano navodi sigurnosne skenere na pogrešan zaključak, a svaki od njih proizlazi iz sažimanja višedijelnog pitanja u odgovor s da ili ne. Filtar šifriranja Identity je najčišći primjer. Rječnik /Encrypt je prisutan, datoteka se prijavljuje kao šifrirana, a ipak nizovi i tokovi prolaze kroz filtar Identity nepromijenjeni, tako da je stvarni sadržaj običan tekst. Rješenje je čitanje StringFilterIdentity i StreamFilterIdentity prije proglašavanja bilo čega zaštićenim.

Podjela metapodataka je suptilnija. EncryptMetadata se može razlikovati od ostatka dokumenta u oba smjera, ostavljajući šifriranu datoteku s čitljivim XMP paketom ili, rjeđe, obrnuto. "Datoteka je šifrirana" ne govori ništa o tome jesu li njezini metapodaci šifrirani, što je važno u trenutku kada indeksator ili pravilo usmjeravanja posegnu za naslovom. Ugrađene datoteke dodaju treću os: PDF dopušta namjenski filtar šifriranja samo za privitke, tako da privitci mogu biti jedini šifrirani dio inače otvorenog dokumenta, ili jedini dio s običnim tekstom u šifriranom dokumentu. Snimite tri dodjele filtara kao zasebna polja za nizove, tokove i ugrađene datoteke i nijedna vas od ovih zamki ne može uhvatiti. Pohranite jedan boolean i pogrešna procjena je samo pitanje vremena.

Uklanjanje šifriranja i njegov odabir za nove datoteke

Revizija često završava odlukom o uklanjanju zaštite, a mehanika tu nije prepreka. DecryptFile(InputFileName, OutputFileName, Password) zapisuje dešifriranu kopiju bez potpunog učitavanja, a Decrypt na učitanom dokumentu radi isto u memoriji nakon što je datoteka već otvorena. Obje zahtijevaju valjanu lozinku; nijedna ne zaobilazi kriptografiju. Prava prepreka su pravila, a ne kôd, stoga neka vaša pravila unosa jasno navode kada je uklanjanje dopušteno i zabilježite klasu lozinke koja ga je autorizirala, jer sam tehnički korak ne ostavlja trag.

Izbor za novi izlaz je uži nego što implicira pet vrijednosti Snage. Koristite Snagu 4, AES-256 reviziju 6, osim ako ne morate otvarati datoteke u preglednicima starijima od Acrobata X. Snaga 2, AES-128, je pragmatični minimum za zastarjelu flotu preglednika koja se ne može nadograditi. RC4 opcije pod 0 i 1 su tu kako biste mogli čitati i revidirati povijesne arhive, a ne kako biste s njima proizvodili bilo što novo; posezanje za njima u dizajnu iz 2026. godine znak je da je zahtjev s gornjeg toka zastario.

Stanje šifriranja izravno utječe na odluke o potpisivanju, budući da radno okruženje koje validira i potpisuje dokumente treba istu disciplinu ponovnog čitanja na koju se ova revizija oslanja. To je područje pokriveno u članku o radnom okruženju za usklađenost i potpisivanje. Kada skupni posao primjenjuje EncryptFile na tisuće velikih dokumenata, vodič za izravan pristup velikim PDF-ovima pokazuje kako održati memoriju stabilnom dok radi. Cjelovita referenca API-ja za šifriranje nalazi se na PDFlibPas stranici proizvoda.