跳到內容

疑難排解:簽章與時間戳記失敗

下列條目涵蓋引擎透過 NextPDF\Exception\SignatureExceptionNextPDF\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 會設為你嘗試的層級。
  • 解法。
    1. 安裝提供者:執行 composer require nextpdf/enterprise
    2. 重新執行簽署呼叫。
    3. 若無法安裝該提供者,請改為要求核心套件能產生的 B-BB-T
  • 相關連結。 例外狀況參考

條目:簽章層級無法達成,呼叫遭拒

標題為「條目:簽章層級無法達成,呼叫遭拒」的區段
  • 症狀。 SignatureLevelUnreachableException,訊息格式為 PAdES level "<x>" is unreachable (highest achievable: "<y>")
  • 可能原因。 你要求的合規層級需要簽署時尚未可用的基礎設施——最常見的是 B-T 以上層級所需的時間戳記授權機構。引擎採取失敗即關閉(fail-closed)的做法:它不會悄悄降級後仍對外宣稱較高的層級。
  • 證據/診斷。 getContext() 會回傳 requestedLevelhighestAchievableLevelreasonreason 欄位會說明基礎設施的缺口所在。這是預設的失敗即關閉行為,用來防止文件宣稱達到其實未達到的層級。
  • 解法。
    1. 閱讀 reason 欄位,找出缺少的基礎設施。
    2. 補上缺少的元件——例如設定一個時間戳記授權機構——然後重新執行呼叫。
    3. 若要刻意接受較低的層級,請把 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
  • 解法。
    1. 設定一個時間戳記授權機構用戶端,並把它傳給協調器。
    2. 重新執行呼叫。
    3. 若要產生不需要時間戳記的層級,請要求 B-B
  • 相關連結。 例外狀況參考

條目:時間戳記授權機構的端點 URL 為空

標題為「條目:時間戳記授權機構的端點 URL 為空」的區段
  • 症狀。 SignatureException,結尾為 TSA endpoint URL is empty
  • 可能原因。 建構時間戳記授權機構用戶端時,提供的端點 URL 為空。
  • 證據/診斷。 工廠方法 SignatureException::tsaUrlEmpty() 會產生這則訊息。這是組態缺陷,而非網路失敗。
  • 解法。
    1. 在時間戳記授權機構用戶端上設定一個非空的端點 URL,例如 https://timestamp.example.com/tsa
    2. 若你要求的層級並不需要時間戳記,請改為移除時間戳記授權機構用戶端的接入設定。
    3. 重新執行呼叫。
  • 相關連結。 例外狀況參考

條目:緩衝區中缺少簽章 placeholder(佔位符)

標題為「條目:緩衝區中缺少簽章 placeholder(佔位符)」的區段
  • 症狀。 SignatureException,結尾為 no /Contents <…> field found in PDF buffer (signature placeholder missing)
  • 可能原因。 簽署階段在一個沒有預留簽章容器的緩衝區上執行,因此沒有地方可寫入簽章。
  • 證據/診斷。 工廠方法 SignatureException::signatureContentsNotFound() 會產生這則訊息。
  • 解法。
    1. 請確認簽章欄位及其佔位符在簽署階段執行之前就已寫入。
    2. 重新執行管線,讓佔位符在簽署開始時已存在。
  • 相關連結。 例外狀況參考

條目:撤銷狀態未知(OCSP 回應者婉拒)

標題為「條目:撤銷狀態未知(OCSP 回應者婉拒)」的區段
  • 症狀。 SignatureException,結尾為 OCSP responder returned non-successful OCSPResponseStatus "<status>"
  • 可能原因。 OCSP 回應者未回傳 successful 狀態,因此未產生任何撤銷主張。引擎遵循 RFC 6960 §4.2.1(並在原始碼中引用):唯有 successful (0) 狀態才允許含有內容的回應主體。引擎不會把遭拒的回應當成「可信為真」的結果。
  • 證據/診斷。 工廠方法 SignatureException::nonSuccessfulOcspResponseStatus() 會產生這則訊息,並指出回報的狀態,例如 tryLaterinternalError。若是保留或未知的狀態位元組,則改為產生 SignatureException::reservedOcspResponseStatus()
  • 解法。
    1. 在訊息中確認該狀態。若是 tryLater 這類暫時性狀態,請稍後重試撤銷資料的擷取。
    2. 若是 unauthorizedmalformedRequest,請查驗 OCSP 請求的 URL,以及回應者所預期的憑證。
    3. 不要為了取得 B-LT 或 B-LTA 產出物而抑制此失敗;撤銷主張是該層級的一部分。
  • 相關連結。 例外狀況參考
  • 症狀。 SignatureException,結尾為 failed to base64-decode PEM body — input is not valid PEM
  • 可能原因。 憑證鏈中的某個項目不是有效的 PEM——通常是被截斷、夾雜了多餘字元,或是在預期 PEM 的位置提供了二進位 DER 區塊。
  • 證據/診斷。 工廠方法 SignatureException::pemDecodingFailed() 會在組裝憑證鏈時產生這則訊息。
  • 解法。
    1. 逐一檢查鏈上的每張憑證是否有多餘字元或遭截斷。
    2. 以 PEM 格式重新匯出受影響的憑證。
    3. 重新執行簽署呼叫。
  • 相關連結。 加密與權限

條目:私密金鑰型別與演算法不相符

標題為「條目:私密金鑰型別與演算法不相符」的區段
  • 症狀。 SignatureException,結尾為 expected private key of type "<x>" for the configured algorithm but got "<y>"
  • 可能原因。 載入的私密金鑰與所設定的簽章演算法不相符——例如使用 RSA 金鑰卻選擇 ECDSA。
  • 證據/診斷。 工廠方法 SignatureException::unexpectedKeyType() 會產生這則訊息,並同時點名預期與實際的金鑰類別。
  • 解法。
    1. 確認憑證與金鑰對皆與你選定的演算法相符。
    2. 請將演算法的選擇改為與金鑰相符,或載入與演算法相符的金鑰。
    3. 重新執行簽署呼叫。
  • 相關連結。 例外狀況參考

條目: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()。每一個都會指出觀測到的長度。
  • 解法。
    1. 重新安裝 libsodium PHP 擴充功能;既有資料指出,被精簡或損毀的建置正是長度錯誤資料的原因。
    2. 確認該金鑰是 Ed25519 金鑰,且 OpenSSL 為 1.1.1 或更新版本。
    3. 重新執行簽署呼叫。
  • 相關連結。 例外狀況參考
  • 症狀。 SignatureException,結尾為 no /Type /DocTimeStamp dictionary was emitted into the PDF buffer
  • 可能原因。 B-LTA 封存迴圈雖已執行,文件時間戳記字典卻從未寫進緩衝區,因此產出物會是一份只寫了一半的 B-LTA。引擎會拒絕回傳該產出物。
  • 證據/診斷。 工廠方法 SignatureException::documentTimestampNotEmitted() 會產生這則訊息。這是在最終化時拋出的後置條件失敗。
  • 解法。
    1. 請把輸出視為已捨棄;不要交付這份不完整的產出物。
    2. 使用可連線的時間戳記授權機構,重新執行 B-LTA 管線。
    3. 若失敗反覆出現,請擷取 getContext() 與鏈結的前一個例外狀況,作為缺陷回報。
  • 相關連結。 例外狀況參考
  • 這些工廠方法只有在資訊可用時,才會把 cert_info 設為主體名稱或指紋;對於能力失敗與組態失敗,空的 cert_info 是正常預期。
  • 若 B-LT 或 B-LTA 請求未設定 HTTP 用戶端,會拋出 SignatureException::httpClientMissing()——擷取撤銷資料需要將一個 PSR-18 用戶端傳給協調器。
  • 具 HSM 支援、但沒有簽署器實作的憑證會拋出 SignatureException::hsmSignerMissing();請在簽署前把簽署器接到憑證上。

詞彙表:PAdES 層級 · 撤銷主張