在法律、金融和医疗保健领域,生成大量 PDF 文档是标准做法。然而,生成文档只是成功了一半,保护它们的安全性同样至关重要。当您的归档管道每天处理数百 GB 的 PDF 时,应用 AES-256 加密可能会迅速成为性能瓶颈。
在本文中,我们将探讨如何通过避免内存耗尽并优化加密循环,在 Delphi 中实现高速的 AES-256 PDF 加密。
PDF 加密规范
PDF 安全性已经发生了显着演变。早期版本使用的是 40 位 RC4,这在今天很容易被破解。当前的标准(PDF 1.7 扩展级别 3 和 PDF 2.0)强制要求使用 AES-256 加密。
在 PDF 中,您并不加密整个文件块。文档结构(XRef 表和字典的结构)保持明文。相反,您只加密流(图像和页面内容的原始数据)和字符串(例如元数据文本)。这需要解析器提取数据,应用 AES CBC(密码块链接),然后将其写回。
瓶颈:加载到内存
在加密大型 PDF(例如 2GB 扫描的档案)时,一个常见的错误是在将其传递给加密引擎之前,将整个流加载到 TMemoryStream 中。这会导致 32 位进程中出现内存不足(OOM)异常,并在 64 位进程中导致大量的缺页错误。
Delphi 中的流式加密
解决方案是使用分块的流式方法。使用 Windows 密码学 API(CNG,Next Generation)或像 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 Component 原生支持利用分块流的高速 AES-256 加密。