U pravnim, financijskim i zdravstvenim sektorima generiranje velikih količina PDF dokumenata standardna je praksa. Međutim, izrada dokumenata samo je pola bitke; njihovo osiguranje jednako je kritično. Kada imate arhivski cjevovod koji svakodnevno obrađuje stotine gigabajta PDF-ova, primjena AES-256 enkripcije može brzo postati usko grlo performansi.
U ovom ćemo članku istražiti kako postići brzu AES-256 PDF enkripciju u Delphiju izbjegavanjem iscrpljivanja memorije i optimizacijom kriptografskih petlji.
Specifikacija PDF enkripcije
Sigurnost PDF-a značajno se razvila. Rane verzije koristile su 40-bitni RC4, koji je danas trivijalno provaliti. Trenutni standard (PDF 1.7 Extension Level 3 i PDF 2.0) nalaže AES-256 enkripciju.
U PDF-u ne šifrirate cijeli blok datoteke. Struktura dokumenta (XRef tablica i struktura rječnika) ostaje u čistom tekstu (plaintext). Umjesto toga, šifrirate tokove (sirovi podaci za slike i sadržaj stranice) i nizove (kao što je tekst metapodataka). To zahtijeva od parsera da izdvoji podatke, primijeni AES CBC (Cipher Block Chaining) i zapiše ih natrag.
Usko grlo: Učitavanje u memoriju
Uobičajena pogreška pri šifriranju masivnog PDF-a (npr. skenirane arhive od 2 GB) je učitavanje cijelog toka u TMemoryStream prije nego što se proslijedi kriptografskom motoru. To dovodi do Out-Of-Memory (OOM) iznimaka u 32-bitnim procesima i masivnih grešaka stranica (page faulting) u 64-bitnim procesima.
Strujanje enkripcije (Streaming Encryption) u Delphiju
Rješenje je korištenje pristupa strujanja u komadima (chunked). Korištenjem Windows Cryptography API: Next Generation (CNG) ili biblioteke poput OpenSSL-a, možete čitati PDF tok u blokovima od 64 KB, šifrirati blok i izravno ga zapisati u izlazni disk tok.
Ovdje je konceptualni Delphi primjer koji demonstrira petlju šifriranja u međuspremniku za tok:
uses
System.Classes, System.SysUtils;
const
BUFFER_SIZE = 65536; // 64KB chunks
// This represents your AES-256 encryption routine
procedure EncryptStreamChunk(const InBuffer; var OutBuffer; BytesRead: Integer; const Key: TBytes; const IV: TBytes);
begin
// Call to Windows CNG (BCryptEncrypt) or OpenSSL (EVP_EncryptUpdate)
// ...
end;
procedure EncryptLargePDFStream(InputStream, OutputStream: TStream; const Key, IV: TBytes);
var
InBuffer, OutBuffer: array of Byte;
BytesRead: Integer;
begin
SetLength(InBuffer, BUFFER_SIZE);
// AES CBC requires padding, so the output buffer must be slightly larger
SetLength(OutBuffer, BUFFER_SIZE + 16);
InputStream.Position := 0;
OutputStream.Position := 0;
repeat
BytesRead := InputStream.Read(InBuffer[0], BUFFER_SIZE);
if BytesRead > 0 then
begin
EncryptStreamChunk(InBuffer[0], OutBuffer[0], BytesRead, Key, IV);
// Write the encrypted cipher text directly to disk
OutputStream.Write(OutBuffer[0], BytesRead); // Note: padding logic omitted for brevity
end;
until BytesRead < BUFFER_SIZE;
end;
Optimizacija kriptografskog pozadinskog sustava
Delphi programeri imaju nekoliko izbora za AES pozadinski sustav (backend):
- Izvorne Delphi implementacije: Lako ih je implementirati, ali su često sporije jer se izvršavaju isključivo u softveru.
- Windows CNG (BCrypt): Visoko optimiziran i može koristiti hardversko ubrzanje (AES-NI instrukcije na modernim Intel/AMD procesorima).
- OpenSSL (libcrypto): Industrijski standard, nevjerojatno brz, ali zahtijeva isporuku vanjskih DLL-ova.
Za poslužiteljske aplikacije visoke propusnosti, hardverski ubrzan AES-NI je obavezan. Kada koristite Windows CNG u Delphiju, mapiranje funkcije BCryptEncrypt omogućuje vašoj aplikaciji da prebaci teški posao na namjenski kriptografski silicij procesora, učinkovito smanjujući troškove enkripcije na gotovo nulu.
Zaključak
Prilikom šifriranja PDF-ova u gigabajtnim razmjerima, oslonite se na usitnjavanje toka umjesto na puno pohranjivanje u memoriju i osigurajte da vaš kriptografski pozadinski sustav koristi hardversko AES-NI ubrzanje. Ova kombinacija jamči da vaš arhivski cjevovod radi brzinom vaših NVMe pogona, umjesto da bude ograničen procesorom (CPU-bound).
Napomena: Brza AES-256 enkripcija s korištenjem strujanja u komadima izvorno je podržana u HotPDF VCL Component.