跳转到内容

故障排查:签章与时间戳失败

这些条目涵盖引擎通过 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 属于正常预期。
  • 未配置 HTTP 客户端的 B-LT 或 B-LTA 请求会抛出 SignatureException::httpClientMissing()——获取撤销数据需要一个传给协调器的 PSR-18 客户端。
  • 没有签署器实现的 HSM 托管凭证会抛出 SignatureException::hsmSignerMissing();请在签署前把签署器接入凭证。

词汇表:PAdES 层级 · 撤销主张