加密 (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');