既存の署名を検査し、信頼境界を理解する
このレシピでは、Core インスペクターを使用して PDF に署名が含まれているかを検出し、その境界を明確にします。署名を検出することは、その署名を検証することではありません。暗号的検証、信頼パス検証、失効確認は、Premium または外部の検証器で行います。
- Core をインストール済みであること:
composer require nextpdf/core:^3。 - 検査対象の PDF ファイル。
- PDF のバイト列を読み込みます。
- 続いて、
Inspectorを作成し、inspect()を呼び出します。 - 返された
InspectResult::$hasSignedを読み取ります。trueは、署名辞書がファイル内に存在することを意味します。 - 周辺情報を把握するため、
InspectResult::$isEncryptedとリスクフラグを読み取ります。 - 暗号的な判定を行うために、ファイルを検証器へ渡します。インスペクターが報告するのは存在の有無であり、有効性ではありません。
以下の図は、2 つのことを示しています。1 つはこのレシピが明確にする境界、つまり 存在は有効性ではない という点です。もう 1 つは、実際の検証でなお必要となるチェックの全体像です。
<?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 構造、バイトレンジダイジェスト、署名証明書、証明書チェーン、失効状態は確認しません。改ざんされたファイルでも、hasSigned = trueを報告する場合があります。存在を完全性や作成者の証明として扱ってはなりません。 - 完全な検証に必要なもの。 完全な判定では、バイトレンジダイジェストを再計算して比較し(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 エディションに同梱されています。もう 1 つのサポートされる経路は、外部のバリデーターです。 - 検査の深度とサイドカー(SIDECAR-001)。 デフォルトの
new Inspector()には、Spectrum サイドカーが構成されていません。サイドカーがない場合、結果を返すのはInspectDepth::Quickのみです。InspectDepth::Quickは、プロセス内の PHP フォールバックを使用します。InspectDepth::StandardとInspectDepth::Fullは、いずれもサイドカーを必要とします。サイドカーが利用できない場合、これらはコードINSPECT-SIDECAR-001(“Spectrum sidecar is required for Standard/Full depth inspection”、retryable = true)とともにInspectExceptionをスローします。InspectConfigコンストラクターの デフォルトの深度はStandardです。したがって、素のnew InspectConfig()(またはnew InspectConfig(depth: InspectDepth::Standard))は、オフラインで 使用できません。hasSignedを読み取る前に SIDECAR-001 をスローします。オフラインでの存在検出には、このレシピと同様にInspectConfig::quick()を使用します。Core では、いずれの深度でも暗号的な署名検証は行いません。 - 空の入力。 空文字列は、コード
INSPECT-INPUT-001とともにInspectExceptionをスローします。読み込みをガードしてください。 - 複数の署名。 存在フラグは、署名の数を数えたり、承認署名と文書タイムスタンプを区別したりしません。署名の数や署名ごとの判定が重要な場合は、専用の検証器を使用してください。
| 記述 | 仕様 | 箇条 | リファレンス ID |
|---|---|---|---|
署名値は、署名辞書の Contents エントリーに格納されます。 | ISO 32000-2 | §12.8.1 | |
検証では、署名値を除外して ByteRange 全体にわたってダイジェストを再計算します。 | ISO 32000-2 | §12.8.1 | |
| 長期検証データは DSS に格納されます。 | ETSI EN 319 142-2 | §6.3.1 |
このレシピは、署名の存在を検出します。いずれの署名についても、有効である、信頼されている、または失効していないことを主張するものではありません。その判定は、暗号的な検証器が担います。