檢查既有簽章並釐清信任邊界
這則 recipe(範例)會用 Core inspector 偵測一份 PDF 是否帶有簽章,並劃清邊界。偵測到簽章並不代表已完成驗證。密碼學驗證、信任路徑驗證與撤銷檢查屬於 Premium 或外部範疇。
先決條件
標題為「先決條件」的區段- 已安裝 Core:
composer require nextpdf/core:^3。 - 一份要檢查的 PDF 檔。
- 讀取 PDF 位元組。
- 建立一個
Inspector並呼叫inspect()。 - 讀取
InspectResult::$hasSigned。true表示檔案中存在簽章字典。 - 讀取
InspectResult::$isEncrypted與風險旗標,作為背景脈絡。 - 將檔案交給驗證器,由驗證器做出密碼學判定。inspector 回報的是存在性,而非有效性。
下方圖示呈現兩件事:本則 recipe 釐清的邊界,也就是存在不等於有效;以及真正驗證仍須完成的完整檢查項目。
完整範例
標題為「完整範例」的區段<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Inspect\Inspector;use NextPDF\Inspect\InspectConfig;
$pdfData = file_get_contents(__DIR__ . '/incoming.pdf');if ($pdfData === false || $pdfData === '') { fwrite(STDERR, "Cannot read incoming.pdf\n"); exit(1);}
$inspector = new Inspector();
// InspectConfig::quick() selects InspectDepth::Quick. This is the only// depth that runs offline: a default Inspector has no Spectrum sidecar,// and without a sidecar Quick is the sole path that returns a result.// Standard and Full require the sidecar (see the SIDECAR-001 edge case).$result = $inspector->inspect( $pdfData, InspectConfig::quick(),);
// hasSigned reports the PRESENCE of a signature dictionary.// It does NOT mean the signature verifies.if ($result->hasSigned) { echo "A signature is present in incoming.pdf\n"; echo "Encrypted: " . ($result->isEncrypted ? 'yes' : 'no') . "\n"; echo "Next step: run a cryptographic verifier before trusting it.\n";} else { echo "No signature found in incoming.pdf\n";}預期輸出
標題為「預期輸出」的區段對於已簽署的輸入:
A signature is present in incoming.pdfEncrypted: noNext step: run a cryptographic verifier before trusting it.對於未簽署的輸入:
No signature found in incoming.pdf邊界案例
標題為「邊界案例」的區段- 存在不等於有效 — 邊界。
InspectResult::$hasSigned只會回報檔案中存在一個簽章字典。它不會檢查 CMS 結構、byte-range 摘要、簽署憑證、憑證鏈或撤銷狀態。遭竄改的檔案仍可能回報hasSigned = true。絕不可把存在性當成完整性或作者身分的證明。 - 完整驗證需要什麼。 一次完整判定會重新計算 byte-range 摘要並加以比對(ISO 32000-2 §12.8.1),驗證 CMS SignedData,建立並檢查通往受信任錨點的 X.509 路徑,並透過 OCSP 或 CRL 檢查撤銷。對於長期保存的輸入,驗證資料存放在 DSS 中(ETSI EN 319 142-2 §6.3.1)。這些操作由
SignerInterface與LtvManagerInterface契約背後的實作執行;正式環境實作隨 Pro 與 Enterprise 版本提供。外部驗證器則是另一條受支援的路徑。 - 檢查深度與 sidecar(旁路服務,SIDECAR-001)。 預設的
new Inspector()不會設定 Spectrum sidecar。沒有 sidecar 時,只有InspectDepth::Quick會回傳結果。InspectDepth::Quick會使用行程內 PHP 後援路徑。InspectDepth::Standard與InspectDepth::Full都需要 sidecar。若沒有可用的 sidecar,它們會丟出InspectException,代碼為INSPECT-SIDECAR-001(「Spectrum sidecar is required for Standard/Full depth inspection」,retryable = true)。InspectConfig建構式的 預設深度是Standard。因此,沒帶參數的new InspectConfig()(或new InspectConfig(depth: InspectDepth::Standard))無法離線使用。它會在讀取hasSigned之前就丟出 SIDECAR-001。請改用InspectConfig::quick()進行離線存在性偵測,就像本則 recipe 所示。Core 中沒有任何一種深度會執行密碼學上的簽章驗證。 - 空白輸入。 空字串會丟出
InspectException,代碼為INSPECT-INPUT-001。請先防護讀取結果。 - 多個簽章。 存在旗標不會計算簽章數量,也不會區分核可簽章與文件時間戳記。當簽章數量或逐一簽章的判定結果重要時,請使用專用驗證器。
符合性
標題為「符合性」的區段| 陳述 | 規範 | 條款 | 參考 ID |
|---|---|---|---|
簽章值存放在簽章字典的 Contents 項目中。 | ISO 32000-2 | §12.8.1 | |
驗證會在 ByteRange 上重新計算摘要,並排除簽章值本身。 | ISO 32000-2 | §12.8.1 | |
| 長期驗證資料存放在 DSS 中。 | ETSI EN 319 142-2 | §6.3.1 |
本則 recipe 只偵測簽章。它不會主張任何簽章有效、受信任或未撤銷。該判定屬於密碼學驗證器的職責。