Technical Article

Didelės spartos AES-256 PDF šifravimas didžiuliams dokumentams

Teisės, finansų ir sveikatos priežiūros sektoriuose didelių PDF dokumentų kiekių generavimas yra standartinė praktika. Tačiau dokumentų sukūrimas yra tik pusė darbo; ne mažiau svarbu juos apsaugoti. Kai jūsų archyvavimo konvejeris kasdien apdoroja šimtus gigabaitų PDF failų, AES-256 šifravimo taikymas gali greitai tapti našumo butelio kakliuku.

Šiame straipsnyje panagrinėsime, kaip „Delphi“ aplinkoje pasiekti didelės spartos AES-256 PDF šifravimą, išvengiant atminties išsekimo ir optimizuojant kriptografinius ciklus.

PDF šifravimo specifikacija

PDF saugumas smarkiai evoliucionavo. Ankstyvosios versijos naudojo 40 bitų RC4, kurį šiandien nulaužti yra labai lengva. Dabartinis standartas (PDF 1.7 Extension Level 3 ir PDF 2.0) reikalauja AES-256 šifravimo.

PDF faile nėra šifruojamas visas failo blokas. Dokumento struktūra („XRef“ lentelė ir žodynų struktūra) išlieka atviruoju tekstu (angl. plaintext). Vietoj to šifruojami srautai (angl. Streams) (neapdoroti vaizdų ir puslapių turinio duomenys) ir eilutės (angl. Strings) (pavyzdžiui, metaduomenų tekstas). Tai reikalauja, kad analizatorius išskirtų duomenis, pritaikytų AES CBC (angl. Cipher Block Chaining) algoritmą ir įrašytų juos atgal.

Butelio kakliukas: įkėlimas į atmintį

Dažna klaida šifruojant didžiulį PDF failą (pvz., 2 GB nuskaitytą archyvą) yra viso srauto įkėlimas į TMemoryStream prieš perduodant jį kriptografiniam varikliui. Tai sukelia atminties išsekimo (angl. Out-Of-Memory, OOM) išimtis 32 bitų procesuose ir didžiulį puslapių klaidų (angl. page faulting) kiekį 64 bitų procesuose.

Srautinis šifravimas „Delphi“ aplinkoje

Sprendimas yra naudoti dalimis suskirstytą, srautinį (angl. chunked, streaming) metodą. Naudojant „Windows Cryptography API: Next Generation“ (CNG) arba tokią biblioteką kaip „OpenSSL“, galite skaityti PDF srautą 64 KB blokais, užšifruoti bloką ir įrašyti jį tiesiai į išvesties disko srautą.

Štai konceptualus „Delphi“ pavyzdys, demonstruojantis buferizuotą šifravimo ciklą srautui:

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;

Kriptografinės vidinės dalies (angl. Backend) optimizavimas

„Delphi“ kūrėjai turi kelis pasirinkimus AES vidinei daliai:

  • Natyvūs „Delphi“ diegimai: lengva įdiegti, bet dažnai lėtesni, nes jie vykdomi tik programiškai.
  • „Windows CNG“ (BCrypt): labai optimizuotas ir gali naudoti aparatinį spartinimą (AES-NI instrukcijas moderniuose „Intel“ / AMD procesoriuose).
  • „OpenSSL“ (libcrypto): pramonės standartas, neįtikėtinai greitas, bet reikalauja kartu platinti išorines DLL bibliotekas.

Didelio pralaidumo serverių programoms aparatiškai spartintas AES-NI yra privalomas. „Delphi“ aplinkoje naudojant „Windows CNG“, funkcijos BCryptEncrypt atvaizdavimas leidžia jūsų programai perkelti sunkų darbą į procesoriaus dedikuotą kriptografinį silicį, taip efektyviai sumažinant šifravimo pridėtines išlaidas beveik iki nulio.

Išvada

Šifruodami gigabaitų dydžio PDF failus, pasikliaukite srautų skaidymu dalimis, o ne visišku buferizavimu atmintyje, ir užtikrinkite, kad jūsų kriptografinė vidinė dalis naudoja aparatinį AES-NI spartinimą. Šis derinys garantuoja, kad jūsų archyvavimo konvejeris veiks jūsų NVMe diskų greičiu, o ne bus ribojamas procesoriaus (angl. CPU-bound).

Pastaba: didelės spartos AES-256 šifravimas naudojant dalimis skaidomą srautinį perdavimą yra natūraliai palaikomas „HotPDF VCL“ komponente.