加密 (HasSecurity)
Document 上的 HasSecurity trait 通过 Aes256Encryptor 引擎提供 AES-256 加密。TCPDF-Next 仅实现 PDF 2.0 安全处理器(AESV3, Revision 6, V5)— RC4 与 AES-128 已被刻意移除。密码通过 SASLprep(RFC 4013)进行规范化以正确处理 Unicode,密钥派生则使用 Algorithm 2.B(迭代 SHA-256/384/512)。
快速参考
| 方法 | 说明 |
|---|---|
setProtection() | 启用 AES-256 加密,设置权限与密码 |
启用加密
use Yeeefang\TcpdfNext\Core\Document;
$pdf = Document::create()
->setProtection(
permissions: ['print', 'copy'],
userPass: 'reader-password',
ownerPass: 'owner-secret-password',
)
->addPage()
->setFont('Helvetica', '', 12)
->cell(0, 10, 'This PDF is AES-256 encrypted', newLine: true)
->save('encrypted.pdf');setProtection() 返回 static,可与所有其他 Document 方法链式串接。
$pdf->setProtection(
array $permissions = [], // 权限标志(参见下表)
string $userPass = '', // 打开文件所需的密码
string $ownerPass = '', // 获取完整访问权限的密码
);用户密码 vs 所有者密码
- 用户密码 — 读者必须输入此密码才能打开并查看 PDF。留空时文件无需提示即可打开,但权限限制仍然有效。
- 所有者密码 — 授予文件的完整访问权限,绕过所有权限限制。留空时,系统会在内部自动生成随机 32 字节的所有者密码。
两种密码在密钥派生前都会经过 SASLprep(RFC 4013)规范化处理,确保 Unicode 密码(如 "Pässwörd")在所有 PDF 阅读器中的行为一致。
权限标志
在 $permissions 数组中传入以下字符串标志的任意组合:
| 标志 | 说明 |
|---|---|
print | 允许打印(低分辨率) |
modify | 允许修改内容 |
copy | 允许提取文字与图片 |
annotate | 允许添加注解 |
fill-forms | 允许填写表单字段 |
extract | 允许无障碍提取 |
assemble | 允许插入、旋转与删除页面 |
print-highres | 允许高分辨率打印 |
当 $permissions 为空时,所有操作皆受限制(需要所有者密码才能执行任何动作)。
仅所有者加密
限制权限但不要求打开密码:
use Yeeefang\TcpdfNext\Core\Document;
$pdf = Document::create()
->setProtection(
permissions: ['print', 'fill-forms'],
ownerPass: 'admin-password',
)
->addPage()
->setFont('Helvetica', '', 12)
->cell(0, 10, 'Open freely, but only print and fill forms.', newLine: true)
->save('restricted.pdf');文件无需密码即可打开,但修改、复制与注解功能会被封锁,除非提供所有者密码。
安全架构
TCPDF-Next 专门实施最强的 PDF 加密标准:
- 算法: AES-256-CBC (AESV3), Revision 6, V5
- 密钥长度: 256 位
- 无旧版支持: RC4 与 AES-128 已被刻意移除
SASLprep 密码规范化
SaslPrep 类(RFC 4013)通过 NFKC Unicode 规范化处理密码、拒绝禁用字符,并强制执行双向文字约束。这确保无论平台或输入方式为何,都能产生相同的哈希值。
密钥派生 — Algorithm 2.B
ISO 32000-2 的 Algorithm 2.B 通过迭代 SHA-256/384/512 哈希(最多 64 轮)派生加密密钥,提供强大的暴力破解抵抗能力。
PDF/A 不兼容
PDF/A 合规文件不允许加密。若尝试在已启用 PDF/A 模式的文件上调用 setProtection(),将抛出 PdfAException:
use Yeeefang\TcpdfNext\Core\Document;
// 这会抛出 PdfAException
$pdf = Document::create()
->setPdfA(true)
->setProtection(permissions: ['print'], ownerPass: 'secret');
// -> throws PdfAException: "Encryption is not allowed in PDF/A documents"若同时需要存档合规性与访问控制,请考虑改用具有权限限制的数字签名。
完整范例
use Yeeefang\TcpdfNext\Core\Document;
$pdf = Document::create()
->setTitle('Confidential Report')
->setAuthor('Security Team')
->setProtection(
permissions: ['print-highres', 'copy'],
userPass: 'open-me',
ownerPass: 'full-access-2026',
)
->addPage()
->setFont('Helvetica', 'B', 18)
->cell(0, 15, 'Confidential Report', newLine: true)
->setFont('Helvetica', '', 12)
->multiCell(0, 6, 'This document is protected with AES-256 encryption. '
. 'Readers can print and copy, but cannot modify or annotate.')
->save('confidential-report.pdf');