使用 AES-256 加密 PDF 并设置权限
这则 recipe(示例)使用 AES-256 加密一份文档。它会设置用户密码和所有者密码,并通过权限位掩码限制可执行的操作。本示例遵循 examples/22-protection.php。
可重现性:为什么这则示例属于
structural,而非bitwise。 一份 AES-256 PDF 永远不可能在两次运行之间做到逐 byte 完全一致,即使输入和密码都相同也是如此。修订版 6 的标准安全处理程序每次加密都会使用强随机数生成器生成 16 组全新的随机字节(user/owner 验证盐与密钥盐) 然后据此推导出文件加密密钥 (ISO 32000-2 §7.6.4 的密钥派生哈希算法)。 AES-256-CBC 对每个对象都使用一组随机初始化向量。文件 trailer 中的/ID同样是由两个字节字符串组成的数组,其中第一个元素是创建时由文件推导出的永久标识符(ISO 32000-2 §14.4)。 因此其可重现性属于structural:测试工具会把加密盐/IV、对象顺序和 trailer 的/ID规范化之后,再比对两次运行,而不是断言不可能成立的逐 byte 一致。
前提条件
标题为“前提条件”的章节- 已安装核心包:
composer require nextpdf/core:^3。 - 已启用 AES-256 加密器所需的
opensslPHP 扩展。
- 创建文档。
- 调用
setEncryption(),务必在addPage()之前。写入任何内容对象之前,必须先配置好加密器。 - 传入用户密码(打开文档时必须提供)、所有者密码(完整访问权限)以及一个权限位掩码。
- 添加内容并保存。写入器会加密每一个对象主体。
完整示例
标题为“完整示例”的章节<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// Permission bits (ISO 32000-2, encryption dictionary P entry):// bit 3 (4) allow printing// bit 4 (8) allow content modification// bit 5 (16) allow text extraction / copying// bit 6 (32) allow annotation and form editing// Grant printing only:$permissions = 4;
$doc = Document::createStandalone();$doc->setTitle('Encrypted Document');
// setEncryption() MUST run before addPage(). Order matters.$doc->setEncryption( userPassword: 'open-me', ownerPassword: 'owner-secret', permissions: $permissions,);
$doc->addPage();$doc->setFont('helvetica', '', 12);$doc->cell(0, 10, 'This document is encrypted with AES-256.', newLine: true);
$doc->save(__DIR__ . '/encrypted.pdf');
echo "Wrote encrypted.pdf (AES-256, printing only)\n";预期输出
标题为“预期输出”的章节Wrote encrypted.pdf (AES-256, printing only)打开 encrypted.pdf 时会要求输入密码。使用用户密码时,会在受限的权限集合下打开文档。使用所有者密码时,则会以完整访问权限打开文档。
边界情况
标题为“边界情况”的章节- 调用顺序。 如果在
addPage()之后才调用setEncryption(),它不会回头加密此前写入的内容。请务必先配置好加密。 - 所有者密码默认值。 所有者密码为空时,引擎会改用用户密码作为所有者密码。如果这两种角色必须区分开,请设置不同的密码。
- 权限语义:边界。 这些权限位由符合规范的阅读器遵守。它们并不是通过密码学手段强制执行的:忽略这些位的阅读器,或搭配所有者密码使用的工具,仍可执行受限的操作。请将权限视为发送给协作软件的策略信号,而不是能够抵御有意规避者的访问控制。
- PDF/A 冲突。 PDF/A 禁止使用
Encrypttrailer 键。对 PDF/A 文档调用setEncryption(),无论顺序如何,都会抛出不兼容异常。请参阅 PDF/A-4 一致性 gate。 - AES-256-GCM。 如果主机的 OpenSSL 或 libsodium 提供此加密算法,
useAesGcm()会选用 ISO/TS 32003 的 GCM 批量加密。否则它会抛出InvalidConfigException。
一致性
标题为“一致性”的章节| 陈述 | 规范 | 条款 | 参考 ID |
|---|---|---|---|
| 标准安全处理程序定义了加密算法和密钥长度。 | ISO 32000-2 | §7.6 | |
加密字典的 P 条目包含权限位。 | ISO 32000-2 | §7.6 |
对于没有密码的各方,加密会保护内容的机密性。权限位对阅读器而言只是建议性的,单凭它们本身并不能阻止不符合规范的工具进行操作。