Technical Article

針對大型文件的高速 AES-256 PDF 加密

在法律、金融與醫療保健領域,產生大量的 PDF 文件是標準做法。然而,產生文件只成功了一半;保護它們的安全同樣重要。當您有一個每天處理數百 GB PDF 的歸檔管線時,套用 AES-256 加密很快就會成為效能瓶頸。

在本文中,我們將探討如何透過避免記憶體耗盡並最佳化加密迴圈,在 Delphi 中實現高速 AES-256 PDF 加密。

PDF 加密規範

PDF 的安全性已有了顯著的演進。早期版本使用 40 位元的 RC4,這在今天很容易被破解。目前的標準 (PDF 1.7 延伸層級 3 與 PDF 2.0) 強制要求使用 AES-256 加密。

在 PDF 中,您不會加密整個檔案區塊。文件結構 (XRef 表格與字典的結構) 保持明文。相反地,您會加密串流 (Streams) (圖片與頁面內容的原始資料) 與字串 (Strings) (例如詮釋資料文字)。這需要解析器擷取資料,套用 AES CBC (密碼區塊連結),然後將其寫回。

瓶頸:載入記憶體

加密大型 PDF (例如 2GB 的掃描存檔) 時常見的錯誤是,在將串流傳遞給密碼引擎之前,將整個串流載入 TMemoryStream 中。這會導致在 32 位元處理程序中發生記憶體不足 (OOM) 例外,以及在 64 位元處理程序中產生大量的分頁錯誤。

在 Delphi 中進行串流加密

解決方案是採用分塊的串流處理方法。使用 Windows 密碼編譯 API:次世代 (CNG) 或類似 OpenSSL 的函式庫,您可以讀取 64KB 區塊的 PDF 串流,加密該區塊,並將其直接寫入輸出磁碟串流。

以下是一個概念性的 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):高度最佳化,可利用硬體加速 (現代 Intel/AMD CPU 上的 AES-NI 指令)。
  • OpenSSL (libcrypto):業界標準,速度極快,但需要隨附外部 DLL。

對於高吞吐量的伺服器應用程式,硬體加速的 AES-NI 是必備的。在 Delphi 中使用 Windows CNG 時,對映 BCryptEncrypt 函式允許您的應用程式將繁重的工作卸載到 CPU 專用的加密矽晶片上,有效地將加密負擔減少到近乎零。

結論

當加密 GB 級的 PDF 時,請依賴串流分塊而非完整的記憶體緩衝,並確保您的加密後端利用硬體 AES-NI 加速。這個組合保證了您的歸檔管線能以您的 NVMe 磁碟機的速度運作,而不是受限於 CPU。

備註:HotPDF VCL 元件 原生支援利用分塊串流的高速 AES-256 加密。