疑難排解:簽章與時間戳記失敗
適用範圍
標題為「適用範圍」的區段下列條目涵蓋引擎透過 NextPDF\Exception\SignatureException 與 NextPDF\Security\Signature\Exception\SignatureLevelUnreachableException 拋出的簽章失敗。每則條目都列出確切的工廠方法或類別,讓你能從訊息與 getContext() 確認原因,不必臆測。
用語提醒:引擎不會宣告簽章有效,也不會宣告文件受到保護。它只回報偵測到的失敗。請把每則解法都視為「移除一個已回報原因」的步驟。
條目:無法產生 PAdES「B-LT」或「B-LTA」層級
標題為「條目:無法產生 PAdES「B-LT」或「B-LTA」層級」的區段- 症狀。
SignatureException,訊息結尾為nextpdf/enterprise package is required for B-LT/B-LTA signatures。 - 可能原因。 缺少具備長期驗證(long-term-validation)能力的提供者。B-LT 與 B-LTA 會內嵌撤銷資料與封存時間戳記;該提供者隨附於
nextpdf/enterprise。 - 證據/診斷。 工廠方法
SignatureException::ltvCapabilityMissing()會產生這則確切訊息。getContext()回傳的signature_level會設為你嘗試的層級。 - 解法。
- 安裝提供者:執行
composer require nextpdf/enterprise。 - 重新執行簽署呼叫。
- 若無法安裝該提供者,請改為要求核心套件能產生的
B-B或B-T。
- 安裝提供者:執行
- 相關連結。 例外狀況參考。
條目:簽章層級無法達成,呼叫遭拒
標題為「條目:簽章層級無法達成,呼叫遭拒」的區段- 症狀。
SignatureLevelUnreachableException,訊息格式為PAdES level "<x>" is unreachable (highest achievable: "<y>")。 - 可能原因。 你要求的合規層級需要簽署時尚未可用的基礎設施——最常見的是 B-T 以上層級所需的時間戳記授權機構。引擎採取失敗即關閉(fail-closed)的做法:它不會悄悄降級後仍對外宣稱較高的層級。
- 證據/診斷。
getContext()會回傳requestedLevel、highestAchievableLevel與reason。reason欄位會說明基礎設施的缺口所在。這是預設的失敗即關閉行為,用來防止文件宣稱達到其實未達到的層級。 - 解法。
- 閱讀
reason欄位,找出缺少的基礎設施。 - 補上缺少的元件——例如設定一個時間戳記授權機構——然後重新執行呼叫。
- 若要刻意接受較低的層級,請把
allowDegradation: true傳給PadesOrchestrator。接著該呼叫會產生highestAchievableLevel,並回報它實際產生的層級。
- 閱讀
- 相關連結。 加密與權限。
條目:需要時間戳記授權機構用戶端,卻未提供
標題為「條目:需要時間戳記授權機構用戶端,卻未提供」的區段- 症狀。
SignatureException,結尾為TSA client is required for level <x> but none was provided。 - 可能原因。 B-T、B-LT 或 B-LTA 的請求需要時間戳記授權機構用戶端,但沒有任何用戶端接到協調器(orchestrator)。
- 證據/診斷。 工廠方法
SignatureException::tsaRequired()會產生這則訊息;getContext()會帶有你嘗試的signature_level。 - 解法。
- 設定一個時間戳記授權機構用戶端,並把它傳給協調器。
- 重新執行呼叫。
- 若要產生不需要時間戳記的層級,請要求
B-B。
- 相關連結。 例外狀況參考。
條目:時間戳記授權機構的端點 URL 為空
標題為「條目:時間戳記授權機構的端點 URL 為空」的區段- 症狀。
SignatureException,結尾為TSA endpoint URL is empty。 - 可能原因。 建構時間戳記授權機構用戶端時,提供的端點 URL 為空。
- 證據/診斷。 工廠方法
SignatureException::tsaUrlEmpty()會產生這則訊息。這是組態缺陷,而非網路失敗。 - 解法。
- 在時間戳記授權機構用戶端上設定一個非空的端點 URL,例如
https://timestamp.example.com/tsa。 - 若你要求的層級並不需要時間戳記,請改為移除時間戳記授權機構用戶端的接入設定。
- 重新執行呼叫。
- 在時間戳記授權機構用戶端上設定一個非空的端點 URL,例如
- 相關連結。 例外狀況參考。
條目:緩衝區中缺少簽章 placeholder(佔位符)
標題為「條目:緩衝區中缺少簽章 placeholder(佔位符)」的區段- 症狀。
SignatureException,結尾為no /Contents <…> field found in PDF buffer (signature placeholder missing)。 - 可能原因。 簽署階段在一個沒有預留簽章容器的緩衝區上執行,因此沒有地方可寫入簽章。
- 證據/診斷。 工廠方法
SignatureException::signatureContentsNotFound()會產生這則訊息。 - 解法。
- 請確認簽章欄位及其佔位符在簽署階段執行之前就已寫入。
- 重新執行管線,讓佔位符在簽署開始時已存在。
- 相關連結。 例外狀況參考。
條目:撤銷狀態未知(OCSP 回應者婉拒)
標題為「條目:撤銷狀態未知(OCSP 回應者婉拒)」的區段- 症狀。
SignatureException,結尾為OCSP responder returned non-successful OCSPResponseStatus "<status>"。 - 可能原因。 OCSP 回應者未回傳
successful狀態,因此未產生任何撤銷主張。引擎遵循 RFC 6960 §4.2.1(並在原始碼中引用):唯有successful (0)狀態才允許含有內容的回應主體。引擎不會把遭拒的回應當成「可信為真」的結果。 - 證據/診斷。 工廠方法
SignatureException::nonSuccessfulOcspResponseStatus()會產生這則訊息,並指出回報的狀態,例如tryLater或internalError。若是保留或未知的狀態位元組,則改為產生SignatureException::reservedOcspResponseStatus()。 - 解法。
- 在訊息中確認該狀態。若是
tryLater這類暫時性狀態,請稍後重試撤銷資料的擷取。 - 若是
unauthorized或malformedRequest,請查驗 OCSP 請求的 URL,以及回應者所預期的憑證。 - 不要為了取得 B-LT 或 B-LTA 產出物而抑制此失敗;撤銷主張是該層級的一部分。
- 在訊息中確認該狀態。若是
- 相關連結。 例外狀況參考。
條目:憑證鏈中的項目無法解碼
標題為「條目:憑證鏈中的項目無法解碼」的區段- 症狀。
SignatureException,結尾為failed to base64-decode PEM body — input is not valid PEM。 - 可能原因。 憑證鏈中的某個項目不是有效的 PEM——通常是被截斷、夾雜了多餘字元,或是在預期 PEM 的位置提供了二進位 DER 區塊。
- 證據/診斷。 工廠方法
SignatureException::pemDecodingFailed()會在組裝憑證鏈時產生這則訊息。 - 解法。
- 逐一檢查鏈上的每張憑證是否有多餘字元或遭截斷。
- 以 PEM 格式重新匯出受影響的憑證。
- 重新執行簽署呼叫。
- 相關連結。 加密與權限。
條目:私密金鑰型別與演算法不相符
標題為「條目:私密金鑰型別與演算法不相符」的區段- 症狀。
SignatureException,結尾為expected private key of type "<x>" for the configured algorithm but got "<y>"。 - 可能原因。 載入的私密金鑰與所設定的簽章演算法不相符——例如使用 RSA 金鑰卻選擇 ECDSA。
- 證據/診斷。 工廠方法
SignatureException::unexpectedKeyType()會產生這則訊息,並同時點名預期與實際的金鑰類別。 - 解法。
- 確認憑證與金鑰對皆與你選定的演算法相符。
- 請將演算法的選擇改為與金鑰相符,或載入與演算法相符的金鑰。
- 重新執行簽署呼叫。
- 相關連結。 例外狀況參考。
條目:Ed25519 金鑰或簽章資料格式錯誤
標題為「條目:Ed25519 金鑰或簽章資料格式錯誤」的區段- 症狀。
SignatureException,結尾點名 Ed25519 長度不符——例如Ed25519 signature length <n> ≠ expected 64 bytes,或Ed25519 round-trip self-verify failed。 - 可能原因。 執行階段使用的密碼學建置回傳了長度錯誤的金鑰或簽章資料,或是剛產生的簽章無法以自身的公開金鑰驗證。引擎在原始碼中引用 RFC 8032 §3.4,該節將分離式 Ed25519 簽章固定為 64 個位元組。引擎寧可中止,也不發出無法自我驗證的資料。
- 證據/診斷。 相關的工廠方法為
SignatureException::ed25519SignatureMalformed()、::ed25519RoundTripVerifyFailed()、::ed25519KeyParseFailed()、::ed25519SeedInvalid()、::ed25519SecretKeyMalformed(),以及::ed25519PublicKeyInvalid()。每一個都會指出觀測到的長度。 - 解法。
- 重新安裝 libsodium PHP 擴充功能;既有資料指出,被精簡或損毀的建置正是長度錯誤資料的原因。
- 確認該金鑰是 Ed25519 金鑰,且 OpenSSL 為 1.1.1 或更新版本。
- 重新執行簽署呼叫。
- 相關連結。 例外狀況參考。
條目:未發出封存時間戳記字典
標題為「條目:未發出封存時間戳記字典」的區段- 症狀。
SignatureException,結尾為no /Type /DocTimeStamp dictionary was emitted into the PDF buffer。 - 可能原因。 B-LTA 封存迴圈雖已執行,文件時間戳記字典卻從未寫進緩衝區,因此產出物會是一份只寫了一半的 B-LTA。引擎會拒絕回傳該產出物。
- 證據/診斷。 工廠方法
SignatureException::documentTimestampNotEmitted()會產生這則訊息。這是在最終化時拋出的後置條件失敗。 - 解法。
- 請把輸出視為已捨棄;不要交付這份不完整的產出物。
- 使用可連線的時間戳記授權機構,重新執行 B-LTA 管線。
- 若失敗反覆出現,請擷取
getContext()與鏈結的前一個例外狀況,作為缺陷回報。
- 相關連結。 例外狀況參考。
邊界案例與陷阱
標題為「邊界案例與陷阱」的區段- 這些工廠方法只有在資訊可用時,才會把
cert_info設為主體名稱或指紋;對於能力失敗與組態失敗,空的cert_info是正常預期。 - 若 B-LT 或 B-LTA 請求未設定 HTTP 用戶端,會拋出
SignatureException::httpClientMissing()——擷取撤銷資料需要將一個 PSR-18 用戶端傳給協調器。 - 具 HSM 支援、但沒有簽署器實作的憑證會拋出
SignatureException::hsmSignerMissing();請在簽署前把簽署器接到憑證上。