Technical Article

Високошвидкісне шифрування PDF за допомогою AES-256 для масивних документів

У юридичному, фінансовому та медичному секторах створення великих обсягів PDF-документів є стандартною практикою. Однак створення документів — це лише половина справи; їх захист є не менш критичним. Коли у вас є архівний конвеєр, що щодня обробляє сотні гігабайт PDF-файлів, застосування шифрування AES-256 може швидко стати вузьким місцем у продуктивності.

У цій статті ми розглянемо, як досягти високошвидкісного шифрування PDF за допомогою AES-256 у Delphi, уникаючи вичерпання пам'яті та оптимізуючи криптографічні цикли.

Специфікація шифрування PDF

Безпека PDF значно еволюціонувала. Ранні версії використовували 40-бітний RC4, який сьогодні тривіально зламати. Поточний стандарт (PDF 1.7 Extension Level 3 і PDF 2.0) вимагає шифрування AES-256.

У PDF-файлі ви не шифруєте весь блок файлу. Структура документа (таблиця XRef і структура словників) залишається у вигляді звичайного тексту. Натомість ви шифруєте Потоки (Streams) (необроблені дані для зображень і вмісту сторінок) і Рядки (Strings) (наприклад, текст метаданих). Це вимагає від аналізатора вилучити дані, застосувати AES CBC (Cipher Block Chaining - зчеплення блоків шифротексту) і записати їх назад.

Вузьке місце: завантаження в пам'ять

Поширеною помилкою під час шифрування масивного PDF-файлу (наприклад, відсканованого архіву розміром 2 ГБ) є завантаження всього потоку в `TMemoryStream` перед передачею його криптографічному рушію. Це призводить до винятків Out-Of-Memory (OOM - брак пам'яті) у 32-бітних процесах і масових помилок сторінок (page faulting) у 64-бітних процесах.

Потокове шифрування в Delphi

Рішення полягає у використанні фрагментованого, потокового підходу. Використовуючи Windows Cryptography API: Next Generation (CNG) або бібліотеку на кшталт OpenSSL, ви можете читати потік PDF блоками по 64 КБ, шифрувати блок і записувати його безпосередньо у вихідний дисковий потік.

Ось концептуальний приклад на Delphi, що демонструє буферизований цикл шифрування для потоку:

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;

Оптимізація криптографічного бекенду

Розробники Delphi мають кілька варіантів для бекенду AES:

  • Нативні реалізації Delphi: Легко розгортаються, але часто повільніші, оскільки виконуються суто програмно.
  • Windows CNG (BCrypt): Високооптимізований і може використовувати апаратне прискорення (інструкції AES-NI на сучасних процесорах Intel/AMD).
  • OpenSSL (libcrypto): Галузевий стандарт, неймовірно швидкий, але вимагає постачання зовнішніх файлів DLL.

Для високопродуктивних серверних додатків апаратно-прискорений AES-NI є обов'язковим. При використанні Windows CNG у Delphi зіставлення функції BCryptEncrypt дозволяє вашому додатку перекласти важку роботу на виділений криптографічний кремній процесора, ефективно зменшуючи накладні витрати на шифрування майже до нуля.

Висновок

Під час шифрування гігабайтних PDF-файлів покладайтеся на розбиття потоків на фрагменти, а не на повну буферизацію пам'яті, і переконайтеся, що ваш криптографічний бекенд використовує апаратне прискорення AES-NI. Ця комбінація гарантує, що ваш конвеєр архівування працюватиме зі швидкістю ваших накопичувачів NVMe, а не обмежуватиметься можливостями процесора.

Примітка: Високошвидкісне шифрування AES-256 із використанням фрагментованої потокової передачі нативно підтримується в компоненті HotPDF VCL.