數位簽章 (HasSecurity)
HasSecurity trait 提供 setSignature() 方法用於 PAdES 合規的數位簽章。TCPDF-Next 透過 PadesOrchestrator、TsaClient 與 LTV 模組支援四種簽章等級 — 從基本(B-B)到典藏(B-LTA)。所有簽章方法皆回傳 static 以支援鏈式串接。
快速參考
| 類別 / 列舉 | 用途 |
|---|---|
CertificateInfo | 載入簽署憑證(PEM 或 PKCS#12) |
SignatureLevel | 列舉:PAdES_B_B、PAdES_B_T、PAdES_B_LT、PAdES_B_LTA |
TsaClient | RFC 3161 時間戳記授權用戶端 |
SignatureAppearance | 可見或不可見的簽章小工具 |
OcspClient | RFC 6960 線上撤銷檢查 |
CrlFetcher | RFC 5280 CRL 發佈點擷取 |
簽章等級
| 等級 | 包含內容 | 有效性 |
|---|---|---|
| B-B(基本) | 簽章 + 簽署憑證 | 在憑證未被撤銷期間有效 |
| B-T(時間戳記) | B-B + RFC 3161 時間戳記 | 證明簽章在某個時間點之前已存在 |
| B-LT(長期) | B-T + 包含 OCSP/CRL 回應的 DSS | 憑證過期後仍可驗證 |
| B-LTA(典藏) | B-LT + 文件時間戳記 + 典藏迴圈 | 可無限期驗證 |
載入憑證
從 PEM 檔案
php
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
$cert = CertificateInfo::fromFiles(
certPath: '/path/to/certificate.pem',
keyPath: '/path/to/private-key.pem',
password: 'key-password',
extraCerts: '/path/to/ca-chain.pem', // 選用的中繼憑證
);從 PKCS#12(.p12 / .pfx)
php
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
$cert = CertificateInfo::fromPkcs12(
p12Path: '/path/to/certificate.p12',
password: 'pkcs12-password',
);簽署範例
php
use Yeeefang\TcpdfNext\Core\Document;
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
use Yeeefang\TcpdfNext\Contracts\SignatureLevel;
use Yeeefang\TcpdfNext\Security\Timestamp\TsaClient;
$cert = CertificateInfo::fromFiles(
certPath: '/path/to/certificate.pem',
keyPath: '/path/to/private-key.pem',
password: 'key-password',
);
// PAdES B-B(基本)— 僅簽章
$pdf = Document::create()
->setSignature($cert, SignatureLevel::PAdES_B_B)
->addPage()
->setFont('Helvetica', '', 12)
->cell(0, 10, 'Signed document (B-B)')
->save('signed-bb.pdf');
// PAdES B-T(時間戳記)— 簽章 + 時間戳記
$tsa = new TsaClient('https://freetsa.org/tsr');
$pdf = Document::create()
->setSignature($cert, SignatureLevel::PAdES_B_T, $tsa)
->addPage()
->cell(0, 10, 'Signed with timestamp (B-T)')
->save('signed-bt.pdf');
// PAdES B-LTA(典藏)— 完整長期驗證
$pdf = Document::create()
->setSignature($cert, SignatureLevel::PAdES_B_LTA, $tsa)
->addPage()
->cell(0, 10, 'Archival signature (B-LTA)')
->save('signed-blta.pdf');TsaClient — 時間戳記授權
TsaClient 支援選用的驗證機制。Nonce 驗證與 DNS 固定預設啟用,以防止重放攻擊與 SSRF。
php
$tsa = new TsaClient(
url: 'https://tsa.example.com/timestamp',
user: 'tsa-user',
pass: 'tsa-password',
);B-T 及以上等級皆需要提供 TsaClient。時間戳記依據 RFC 3161 標準,向時間戳記授權機構(TSA)請求可信的時間證明,確保簽章的時間不可否認性。
長期驗證(B-LT / B-LTA)
B-LT 與 B-LTA 等級會自動擷取並嵌入撤銷資料:
- OcspClient — 根據憑證的 AIA 擴充,查詢 OCSP 回應者(RFC 6960)
- CrlFetcher — 從發佈點下載 CRL(RFC 5280)
- DSS(文件安全儲存區) — 將 OCSP 回應與 CRL 儲存在文件安全儲存區中
- VRI(驗證相關資訊) — 每個簽章的驗證資料(選用,依 ETSI 建議)
B-LTA 還會額外新增文件時間戳記,啟動典藏迴圈 — 文件可透過重新加蓋時間戳記來無限期延長有效性。
簽章外觀
預設情況下,簽章為不可見。若要建立可見的簽章小工具:
php
use Yeeefang\TcpdfNext\Security\Signature\SignatureAppearance;
$pdf = Document::create()
->setSignature($cert, SignatureLevel::PAdES_B_T, $tsa)
->setSignatureAppearance(
SignatureAppearance::visible(x: 20, y: 250, w: 80, h: 30)
)
->addPage()
->cell(0, 10, 'Document with visible signature')
->save('visible-signature.pdf');若要明確設定不可見簽章:
php
$pdf->setSignatureAppearance(SignatureAppearance::invisible());簽章等級比較
| 特性 | B-B | B-T | B-LT | B-LTA |
|---|---|---|---|---|
| 數位簽章 | V | V | V | V |
| 簽署憑證 | V | V | V | V |
| RFC 3161 時間戳記 | V | V | V | |
| DSS(OCSP + CRL) | V | V | ||
| 文件時間戳記 | V | |||
| 典藏迴圈 | V | |||
| 憑證過期後可驗證 | V | V | ||
| 無限期可驗證 | V |
方法參考
php
$pdf->setSignature(
CertificateInfo $cert, // 憑證與私密金鑰
SignatureLevel $level, // B-B、B-T、B-LT 或 B-LTA
?TsaClient $tsa = null, // B-T、B-LT、B-LTA 必須提供
);回傳 static 以支援鏈式串接。簽章在呼叫 save() 或 output() 時套用。
簽章演算法透過 phpseclib3 實作:RSA PKCS#1 v1.5(預設,最廣泛的相容性)與 RSASSA-PSS(更強的填充方案,建議新部署使用)。
完整 PKCS#12 範例
php
use Yeeefang\TcpdfNext\Core\Document;
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
use Yeeefang\TcpdfNext\Security\Signature\SignatureAppearance;
use Yeeefang\TcpdfNext\Contracts\SignatureLevel;
use Yeeefang\TcpdfNext\Security\Timestamp\TsaClient;
// 從 PKCS#12 載入憑證
$cert = CertificateInfo::fromPkcs12(
p12Path: '/path/to/certificate.p12',
password: 'pkcs12-password',
);
// 設定時間戳記授權
$tsa = new TsaClient('https://freetsa.org/tsr');
// 建立具有 B-LTA 等級簽章的文件
$pdf = Document::create()
->setTitle('Signed Contract')
->setAuthor('Legal Department')
->setSignature($cert, SignatureLevel::PAdES_B_LTA, $tsa)
->setSignatureAppearance(
SignatureAppearance::visible(x: 20, y: 250, w: 80, h: 30)
)
->addPage()
->setFont('Helvetica', 'B', 18)
->cell(0, 15, 'Service Agreement', newLine: true)
->setFont('Helvetica', '', 12)
->multiCell(0, 6, 'This document has been digitally signed with a PAdES B-LTA '
. 'archival signature. The signature includes a trusted timestamp and '
. 'embedded revocation data for long-term validation.')
->save('signed-contract.pdf');