Technical Article

Vysokorýchlostné šifrovanie AES-256 v PDF pre masívne dokumenty

Ochrana citlivých údajov vo vnútri dokumentov PDF je primárnou požiadavkou pre systémy správy zdravotníckych (HIPAA) a právnych dokumentov. Moderná špecifikácia PDF podporuje 256-bitové šifrovanie AES. Zatiaľ čo zašifrovanie jednoduchej 5-stranovej zmluvy je triviálne a okamžité, aplikácia šifrovania AES-256 na viacgigabajtový archívny PDF súbor môže zastaviť celú operáciu alebo spôsobiť zlyhania pamäte, ak sa to nevykoná s optimalizovanými prúdmi I/O.

Pochopenie štruktúry šifrovania PDF

V dokumente PDF nešifrujete celý blok súboru. Štruktúra dokumentu (tabuľka XRef a štruktúra slovníkov) zostáva vo forme obyčajného textu. Namiesto toho šifrujete Streamy (surové dáta pre obrázky a obsah stránky) a Reťazce (Strings, napríklad text metaúdajov). To si vyžaduje, aby analyzátor extrahoval dáta, aplikoval AES CBC (Cipher Block Chaining) a zapísal ich späť.

Úzke miesto: Načítavanie do pamäte

Bežnou chybou pri šifrovaní obrovského PDF (napríklad 2 GB skenovaného archívu) je načítanie celého streamu do objektu TMemoryStream pred jeho odovzdaním kryptografickému nástroju. Toto vedie k výnimkám nedostatku pamäte (Out-Of-Memory, OOM) v 32-bitových procesoch a k masívnym výpadkom stránok (page faulting) v 64-bitových procesoch.

Postupné šifrovanie prúdov (Streaming) v Delphi

Riešením je použitie sekvenčného prístupu vo väčších blokoch. Použitím rozhrania Windows Cryptography API: Next Generation (CNG) alebo knižnice ako OpenSSL, môžete prečítať stream PDF v 64 KB blokoch, zašifrovať blok a zapísať ho priamo do výstupného streamu disku.

Tu je koncepčný príklad v Delphi demonštrujúci slučku šifrovania s vyrovnávacou pamäťou pre stream:

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;

Optimalizácia kryptografického backendu

Vývojári v Delphi majú na výber z niekoľkých možností pre backend AES:

  • Natívne implementácie v Delphi: Jednoduché na nasadenie, ale často pomalšie, pretože sa vykonávajú čisto softvérovo.
  • Windows CNG (BCrypt): Vysoko optimalizované a môžu využívať hardvérové zrýchlenie (inštrukcie AES-NI na moderných procesoroch Intel/AMD).
  • OpenSSL (libcrypto): Priemyselný štandard, neuveriteľne rýchly, ale vyžaduje distribúciu externých knižníc DLL.

Pre vysokovýkonné serverové aplikácie je hardvérovo akcelerované AES-NI nevyhnutné. Pri použití Windows CNG v Delphi umožňuje mapovanie funkcie BCryptEncrypt vašej aplikácii presunúť náročné úlohy na vyhradený kryptografický čip procesora, čím sa efektívne zníži zaťaženie šifrovaním na hodnotu blízku nule.

Záver

Pri šifrovaní PDF s veľkosťou v gigabajtoch sa spoliehajte na rozdelenie prúdu dát do blokov namiesto úplného ukladania do pamäte a zabezpečte, aby váš kryptografický backend využíval hardvérovú akceleráciu AES-NI. Táto kombinácia zaručuje, že váš archivačný reťazec bude bežať rýchlosťou vašich diskov NVMe, namiesto toho, aby bol obmedzený procesorom.

Poznámka: Vysokorýchlostné šifrovanie AES-256 využívajúce postupné načítavanie po blokoch je natívne podporované v komponente HotPDF VCL Component.