安全性 / 簽章:CMS、RFC 3161 時間戳記、LTV 與信任
本頁說明 NextPDF Core 隨附的簽章介面:產生 CMS 簽章、套用 RFC 3161 時間戳記、依 RFC 5280 驗證憑證鏈,並透過 OCSP 與 CRL 檢查撤銷狀態。內容著重在行為層級。Core 的實作類別屬內部實作——正式環境的程式碼依賴 SignerInterface 這份契約,而不是具體的 NextPDF\Security\Signature 型別。已產生的簽章是否能通過驗證,取決於驗證端以及它所設定的信任錨點。這個結果不在產生端的控制範圍內,本頁會在相關段落明確指出這一點。
composer require nextpdf/core:^3概念總覽
標題為「概念總覽」的區段Core 會從位元組範圍建構 CMS SignedData 結構,再以 DER 編碼存入簽章字典的 Contents 項目——ISO 32000-2 §12.8.1。此結構帶有 SignerInfo 的已簽署屬性,其中包含 content-type 與 message-digest——RFC 5652 §5.3。驗證端會重新計算內容摘要,並與 message-digest 屬性比對。兩者必須相符,簽章才算有效——RFC 5652 §5.4。SignerInfo 也會帶有摘要演算法識別碼與已簽署屬性區塊——RFC 5652 §5。Core 隨附的軟體簽章路徑會透過 phpseclib3 進行簽章:RSA、RSASSA-PSS、ECDSA 與 Ed25519。
RFC 3161 時間戳記是與時間戳記機構(Time-Stamping Authority)之間的一次請求/回應往返,機構會回傳 TSTInfo 結構——RFC 3161 §2.4.1。每個權杖都帶有一個對發行該權杖的 TSA 而言唯一的 serialNumber——RFC 3161 §2.4.2——以及一個以 UTC 表示、代表權杖建立瞬間的 genTime——RFC 3161 §2.4.2。
信任驗證包含兩項檢查。路徑驗證會從簽署者憑證一路驗證到信任錨點,沿途檢查基本限制條件與路徑建構輸入——RFC 5280 §6.1。撤銷檢查會向 OCSP 回應方查詢,或讀取 CRL:一則 OCSP 回應會回報 good、revoked 或 unknown——RFC 6960 §2.2——而回應的 thisUpdate 與 nextUpdate 則界定了該狀態的新鮮度——RFC 6960 §4.2。信任錨點與撤銷新鮮度政策都由呼叫端提供。引擎只依取得的輸入進行驗證,並不隨附內建的信任清單。
API 介面
標題為「API 介面」的區段| 型別 | 種類 | 角色 | 穩定度 | 起始版本 |
|---|---|---|---|---|
SignerInterface | 介面(NextPDF\Contracts) | 呼叫端所依賴的簽章契約 | 穩定 | 1.0.0 |
SignatureLevel | enum(列舉) | PAdES 等級選擇器與可用性偵測 | 穩定 | 1.0.0 |
Rfc5280PathValidator | 介面 | 憑證路徑驗證的進入點(validate(...)) | 穩定(自 3.1.0 起凍結) | 3.1.0 |
RevocationStatus | 列舉 | OCSP / CRL 結果:good、revoked、unknown | 穩定 | 3.1.0 |
CaTrustAnchorBundle | 型別 | 由呼叫端提供的一組信任錨點 | 穩定 | 3.1.0 |
TstInfo | 型別 | 已剖析的 RFC 3161 時間戳記欄位 | 穩定 | 3.2.0 |
SignerInterface::sign() 會回傳一個 SignatureResult,其 toHex() 會產生 /Contents 的十六進位字串,而 cmsSignedData 屬性則持有原始的 DER 位元組。實作這些行為的具體 NextPDF\Security\Signature 類別屬內部實作(在模組資訊清單中標為 stability: internal);它們並非公開 API 的一部分,可能在未提升主版號的情況下變更。請依賴上述契約與列舉。
程式碼範例——快速上手
標題為「程式碼範例——快速上手」的區段<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\SignerInterface;
/** * Produce the CMS SignedData hex for a PDF /Contents field. * * @param SignerInterface $signer A Core or Premium signer. * @param string $byteRange The PDF byte range to sign. * * @return string Hex-encoded CMS SignedData. */function sign(SignerInterface $signer, string $byteRange): string{ return $signer->sign($byteRange)->toHex();}呼叫端依賴的是契約。Core 的軟體簽章器與 Premium 的 HSM 簽章器都滿足 SignerInterface,因此這段程式碼在不同版本之間維持不變。
程式碼範例——正式環境
標題為「程式碼範例——正式環境」的區段<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\SignerInterface;use NextPDF\Contracts\TimestampProviderInterface;use NextPDF\Exception\NextPdfException;use Psr\Log\LoggerInterface;
final readonly class TimestampedSigner{ public function __construct( private SignerInterface $signer, private TimestampProviderInterface $timestamps, private LoggerInterface $logger, ) {}
/** * Sign a byte range, then timestamp the CMS structure. * * The timestamp's trust still depends on the verifier accepting the * Time-Stamping Authority; this method only produces the structure. * * @param string $byteRange The PDF byte range to sign. * * @return array{cms: string, tst: string} */ public function sign(string $byteRange): array { try { $signature = $this->signer->sign($byteRange); $token = $this->timestamps->getTimestamp($signature->cmsSignedData);
return ['cms' => $signature->toHex(), 'tst' => $token]; } catch (NextPdfException $e) { $this->logger->error('Signing failed', ['error' => $e->getMessage()]);
throw $e; } }}時間戳記提供者以注入方式提供,讓每個部署環境都能釘選自己的時間戳記機構(Time-Stamping Authority)。catch 區塊會記錄並重新拋出例外。它絕不吞掉失敗,讓簽章路徑維持 fail-closed(失敗即關閉)。
邊界情況與陷阱
標題為「邊界情況與陷阱」的區段- 已產生的簽章並非已驗證的簽章。路徑驗證與撤銷檢查是在驗證端,並以該驗證端的信任錨點執行。產生端無法判定其結果。
- 位元組範圍摘要會排除簽章值本身。涵蓋
Contents八位元組的摘要無法通過驗證——ISO 32000-2 §12.8.1。 - 撤銷狀態有一個新鮮度時間窗。一則 OCSP 回應的有效期限,只到它的
thisUpdate/nextUpdate區間為止——RFC 6960 §4.2。陳舊的回應無法取代驗證當下的一次即時檢查。 - 引擎不隨附內建的信任清單。
CaTrustAnchorBundle由呼叫端提供;空的 bundle(套件)依設計表示沒有任何憑證鏈能通過驗證。 - OCSP 的
unknown並不等於good。必須把unknown視為無法判定,而非隱含通過——RFC 6960 §2.2。 - HSM 金鑰保管、延後簽章與雲端簽章,以及 PAdES B-LT / B-LTA 產生器,都不在 Core 之中。在 Core 散布版本中選用這些路徑時,會 fail closed(失敗即關閉),並以訊息指出所缺的 Enterprise 元件名稱。
一次軟體簽章只需個位數毫秒。加上時間戳記時,則會多一次往返 TSA 的網路呼叫。憑證一旦載入記憶體,路徑驗證便屬本機作業;撤銷檢查則會為鏈中每張憑證各增加一次 OCSP 或 CRL 擷取。1500 毫秒的整體預算,涵蓋的是在連線已暖機的情況下、向遠端 TSA 取得時間戳記的單次簽章。若對緩慢端點進行撤銷檢查,會超出此預算,應移到請求路徑之外處理。可重現性設定檔為 structural:時間戳記會嵌入簽署的瞬間,因此兩次執行的時間戳記位元組會不同,但文件結構完全相同。
安全性注意事項
標題為「安全性注意事項」的區段這是引擎主要的密碼學邊界,因此威脅模型在此明確列出。位元組範圍由引擎計算,絕不接受由呼叫端提供。簽章路徑為 fail-closed:密碼原語失敗或能力缺口都會拋出具型別的例外,絕不會悄悄降級為較弱的演算法。在需要時間戳記的等級(B-T、B-LT、B-LTA)下,回傳空權杖(empty token)的時間戳記機構(Time-Stamping Authority)屬於終端故障:簽章會被拒絕,而不會悄悄略過時間戳記、以降級狀態發出;除非有已接線的故障處理常式,明確授權一項已記載的降級。信任依設計由呼叫端掌控——錨點與撤銷政策都是輸入,而非引擎預設——因為若由產生端斷定自身的信任,就等於斷定一個只有驗證端能確立的事實。時間戳記的信任取決於對時間戳記機構(Time-Stamping Authority)的信任,而後者可注入,讓每個部署環境都能釘選自己的機構。本頁標示為 export_control_class: legal-review-required,因為其涉及密碼學簽章;依照引用衛生原則,每一份規範性來源皆經改述,且未重製任何內容。
符合性
標題為「符合性」的區段| 主張 | 標準 | 條款 | 佐證 |
|---|---|---|---|
CMS 簽章以 DER 編碼存入簽章字典的 Contents 項目。 | ISO 32000-2 | §12.8.1 | |
| SignerInfo 帶有 content-type 與 message-digest 已簽署屬性。 | RFC 5652 | §5.3 | |
| 驗證端會重新計算內容摘要,並與 message-digest 屬性比對。 | RFC 5652 | §5.4 | |
| 時間戳記權杖由 RFC 3161 TSA 產生,並帶有唯一的 serialNumber 與一個 UTC 的 genTime。 | RFC 3161 | §2.4.1, §2.4.2 | ,, |
| 憑證路徑驗證會檢查基本限制條件,以及從簽署者到信任錨點的路徑輸入。 | RFC 5280 | §6.1 | , |
| OCSP 會回報 certStatus 為 good、revoked 或 unknown,並以 thisUpdate / nextUpdate 為界。 | RFC 6960 | §2.2, §4.2 | , |
所有條款皆以改述方式呈現。NextPDF 不重製規範性原文。權威用語請參閱已發布的標準。
商業脈絡
標題為「商業脈絡」的區段Core 隨附軟體 CMS 簽章器(RSA、RSASSA-PSS、ECDSA、Ed25519)、RFC 3161 時間戳記消費、RFC 5280 路徑驗證,以及 OCSP / CRL 撤銷檢查。HSM 與 PKCS#11 金鑰保管、延後簽章與雲端簽章、PAdES B-LT 與 B-LTA 產生器,以及 FIPS 140-3 密碼學政策設定檔,則隨附於 Pro 與 Enterprise 版本。Core 會在執行期依契約 resolve(解析)這些元件,因此這套開源引擎不帶任何商業相依,升級時 API 也不會改變。
另請參閱
標題為「另請參閱」的區段- PAdES 基準對應——跨 B-B、B-T、B-LT、B-LTA 比較 Core 與 Premium。
- 契約 / 簽章——
SignerInterfaceSPI 與穩定度層級。 - 安全性——加密與更廣泛的簽章介面。
- 符合性——與已簽署封存搭配的設定檔強制執行。
- CMS · RFC 3161 時間戳記 · LTV · DSS · VRI · HSM——詞彙表術語。