Enterprise 版本
NextPDF Enterprise 快速上手
本教學帶你從一個空專案走到兩個可運作的 Enterprise 成果。首先你會驗證一份既有的已簽署 PDF 並讀取它的 MainIndication。接著你會以長期產製器將一份已簽署文件升級為 PAdES B-LT。每個步驟都會顯示你應預期的確切輸出或例外。NextPDF 記述的是能力,而非認證:它並不持有任何 PAdES 或 eIDAS 認證,也不授予任何認證。
此能力隨 NextPDF Enterprise(nextpdf/enterprise)一同提供,並以 Enterprise 層級的授權信封啟用。一個不具備該權利的部署不會載入此能力的類別。比較版本並取得授權。
先決條件
標題為「先決條件」的區段- Composer 已設定為指向私有的 NextPDF 儲存庫。請先依照 安裝與驗證 進行。
- 你已備妥 Enterprise 授權信封,由你在 app.getnextpdf.com 的帳戶下載。授權與啟用 說明了此信封是什麼以及該放在哪裡。
- 步驟 3 需要一份要驗證的已簽署 PDF。B-LT 部分還需要你的簽署者憑證與連往 OCSP/CRL 回應者的網路存取權。
1. 安裝與啟用
標題為「1. 安裝與啟用」的區段引入 Enterprise 套件。它相依於 nextpdf/core 與 nextpdf/pro,因此 Composer 會帶入整個堆疊:
composer require nextpdf/enterprisecomposer show nextpdf/enterprise如果 composer show 印出該套件及其版本,代表安裝成功。現在依照 授權與啟用 的說明,將已簽署的授權信封放到你的部署載入它的位置。單獨安裝套件並不會授予 Enterprise 能力;由已啟用的授權來選定版本。
2. 驗證你的權利
標題為「2. 驗證你的權利」的區段向權利評估器詢問你的授權授予了什麼。你的啟動流程會在啟用期間取得已驗證的 NextPDF\Enterprise\Licensing\LicenseKey;把它傳進去:
<?phprequire __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Licensing\EntitlementEvaluator;use NextPDF\Enterprise\Licensing\LicenseKey;
/** @var LicenseKey|null $license The verified license from activation. */$result = (new EntitlementEvaluator())->evaluate($license);
echo 'status: ' . $result->status->value . PHP_EOL;echo 'edition: ' . ($result->edition?->value ?? 'none') . PHP_EOL;echo 'runtime: ' . ($result->runtimeAllowed ? 'allowed' : 'disabled') . PHP_EOL;在有效的 Enterprise 授權下,你會看到:
status: activeedition: enterpriseruntime: allowed此步驟背後的方法:
public function evaluate(?LicenseKey $license, ?DateTimeImmutable $now = null): EntitlementResult拋出或失敗的情形:它從不拋出例外。缺少授權時會回傳一個失敗即封閉的 EntitlementResult,其 EntitlementStatus::NoLicense 且 runtimeAllowed 為 false(見步驟 4)。
3. 第一手成果
標題為「3. 第一手成果」的區段驗證一份既有的已簽署 PDF
標題為「驗證一份既有的已簽署 PDF」的區段從一份已簽署 PDF 擷取簽章,然後執行基本的 AdES 驗證。此引擎實作了 ETSI EN 319 102-1 的驗證層級;validateBasic() 就是第 5.2 條的流程——結構、摘要、簽章密碼學,以及憑證鏈:
<?phprequire __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Validation\AdESValidationEngine;use NextPDF\Enterprise\Security\Validation\CmsSignatureDataExtractor;use NextPDF\Enterprise\Signature\SignatureExtractor;
$pdf = file_get_contents(__DIR__ . '/contract-signed.pdf');if ($pdf === false) { throw new RuntimeException('Could not read contract-signed.pdf');}
$signatures = (new SignatureExtractor())->extract($pdf);if ($signatures === []) { throw new RuntimeException('The PDF carries no signature dictionary.');}
$engine = new AdESValidationEngine(extractor: new CmsSignatureDataExtractor());$report = $engine->validateBasic( $signatures[0]['signedBytes'], // the exact /ByteRange-covered bytes $signatures[0]['contents'], // the DER CMS SignedData from /Contents);
echo $report->mainIndication->name . PHP_EOL;echo ($report->subIndication?->name ?? '(none)') . PHP_EOL;對於一個結構良好、且通過本範例所設定之基本結構、摘要、密碼學與鏈檢查的簽章,你會看到:
TOTAL_PASSED(none)MainIndication 恰有三種情形:TOTAL_PASSED、TOTAL_FAILED 與 INDETERMINATE。此引擎是失敗即封閉的:一項它無法正面確立的檢查會產出 INDETERMINATE,絕不會靜默通過。這裡的通過是在此引擎的檢查之下的一個驗證結果,而非信任或認證的宣告——信任錨與長期證據屬於 驗證頁面 上更深層的層級。
public function extract(string $pdfData): array拋出或失敗的情形:若輸入不是有效的 PDF,會拋出 InvalidArgumentException。畸形的 /ByteRange 或 /Contents 會產出空字串(失敗即封閉),絕不會產出正面結果。
public function validateBasic(string $signedData, string $signature): ValidationReport拋出或失敗的情形:在驗證失敗時它從不拋出例外。每個缺陷都會對映到一個 ValidationReport 指示,例如 HASH_FAILURE 或 SIG_CRYPTO_FAILURE。
產製一份 PAdES B-LT
標題為「產製一份 PAdES B-LT」的區段現在將一份剛簽署的文件升級為 B-LT。長期產製器會蒐集憑證鏈以及 OCSP/CRL 證據,並寫入文件安全存放區(DSS)。它延續 簽章頁面 上所描述的簽署流程,該流程會提供你輸出緩衝區、物件登錄,以及簽章的 /Contents 十六進位值:
use NextPDF\Enterprise\Security\Ltv\LtvManager;use NextPDF\Security\Signature\CertificateInfo;use NextPDF\Security\Signature\SignatureLevel;
$certInfo = CertificateInfo::fromPkcs12('/secure/signer.p12', $p12Password);
// $httpClient is any PSR-18 client; it fetches OCSP responses and CRLs.$ltv = new LtvManager($certInfo, $httpClient, level: SignatureLevel::PAdES_B_LT);
// $buffer, $registry, and $signatureContentsHex come from the signing pass.$dssObjectNumber = $ltv->enableLtv($buffer, $registry, $signatureContentsHex);回傳值是供文件目錄的 /DSS 項目使用的 DSS 物件編號。產製器預設採用嚴格的撤銷強制執行:缺少撤銷素材會引發例外,而非靜默地輸出一份空洞的「B-LT」檔案。
public function enableLtv(BinaryBuffer $buffer, ObjectRegistry $registry, string $signatureContentsHex): int拋出或失敗的情形:當鏈驗證失敗、當憑證已撤銷,或當嚴格預設下缺少撤銷素材時,會拋出 NextPDF\Enterprise\Security\Ltv\LtvException。
4. 當某處失敗時
標題為「4. 當某處失敗時」的區段status: no_license——信封未載入
標題為「status: no_license——信封未載入」的區段步驟 2 印出 status: no_license 與 runtime: disabled,且結果會帶有警告 No license configured. Enterprise runtime is disabled. Install a license or purchase one at https://nextpdf.dev/pricing。此時一個受權利控管的呼叫會拋出 NextPDF\Accelerator\Exception\SpectrumAuthenticationException,代碼為 SPEC-LIC-001,例如 Capability '...' requires a valid license.。修正方式:依 授權與啟用 放置並啟用信封,然後重跑步驟 2。
InvalidArgumentException: Input does not start with %PDF header
標題為「InvalidArgumentException: Input does not start with %PDF header」的區段SignatureExtractor::extract() 收到的並不是 PDF——可能是錯誤的路徑、一次空的讀取,或一份壓縮過的下載檔。檢查你載入的檔案。空的 $signatures 清單則是另一回事:該檔案是 PDF,但它不帶有 /Type /Sig 字典,因此沒有東西可供驗證。
LtvException: Strict revocation: LTV warning: no revocation data for certificate at chain position 0
標題為「LtvException: Strict revocation: LTV warning: no revocation data for certificate at chain position 0」的區段enableLtv() 無法為某張鏈憑證取得 OCSP 回應或 CRL,而嚴格預設拒絕在沒有證據的情況下寫入 B-LT 宣告。檢查主機是否能連上回應者,或僅在你明確接受一次只警告的執行時才傳入 enforcementMode: RevocationEnforcementMode::PERMISSIVE——除非缺少的撤銷證據已被明確接受並記錄在案,否則絕不要為正式生產或合規工作流程將此類輸出標示為 B-LT。相關:在沒有 TSA 用戶端的情況下請求 B-LTA 會以 LtvException: TSA client required for document timestamps 失敗。
後續前往之處
標題為「後續前往之處」的區段- 簽章:PAdES B-LT / B-LTA、DSS、文件時間戳記——完整的產製器行為、排序規則,以及封存迴圈。
- 簽章驗證——時間式與長期驗證、信任錨、封存鏈。
- 授權——NextPDF Enterprise——權利狀態、寬限期、能力控管。
- NextPDF Enterprise 模組索引——此版本提供的其餘一切。