跳转到内容

签名验证:AdES / PAdES 密码学验证器

NextPDF Enterprise 会以密码学方式验证数字签名。验证端从 PDF 读取 CMS SignedData 或 RFC 3161 时间戳令牌,重新计算摘要、检查签名、将每个签名绑定到其签署凭证,并根据调用方提供的信任锚点存储区验证凭证链——包括凭证策略处理。本页属于行为层级文档,说明哪些项目会被验证、哪些项目会以 fail-closed 方式拒绝、支持哪些算法,以及信任边界位于何处。

这不同于 Validation,后者运行只读的结构性策略检查,并有意不执行任何密码学运算。它也是 签名生成器的验证端对应组件,后者会写入 PAdES B-LT / B-LTA 结构。

Terminal window
composer require nextpdf/enterprise:^3

验证以证据为本,并采用 fail-closed:无法正面确立的检查不会产生正面结果。下列各部分共同构成由 ValidationReport 承载的结果。

CMS / 时间戳令牌的密码学验证。 一个自包含、严格的定长 DER 堆栈会解析 CMS SignedData 与 RFC 3161 时间戳令牌。只有当令牌恰好带有一个 SignerInfo、其签署属性通过严格解析、签署者凭证可解析、message-digest 属性与重新计算的摘要相符、必要的签署凭证(ESS signing-certificate-v2)绑定成立,且 SignerInfo 签名能针对重新标记后的签署属性通过验证时,令牌才会被接受。摘要比对规则遵循 RFC 5652 §5.6 / §5.4 的验证模型:接收端重新计算内容消息摘要,只有当该值等于 messageDigest 签署属性时,签名才有效——验证者绝不信任由生成器提供的摘要。

在 genTime 进行的 TSA 凭证验证。 时间戳的 genTime 是该令牌创建时的 UTC 时刻(RFC 3161 §2.4.2)。TSA 签署凭证会在那个时刻而非「现在」进行验证:其扩展密钥用途必须是单一且关键的 id-kp-timeStamping(RFC 3161 §2.3),并且其有效期间、凭证链、信任锚点来源与撤销都会针对 genTime 进行评估。即使结构上格式良好,只要凭证链无法连接到已配置的信任锚点,就永远无法支撑正面结果。

分离式 PAdES 基本文档签名。 一个具体的提取器会对分离式文档签名运行真正的 AdES / PAdES 基本验证:针对已签署的字节范围重新计算消息摘要并进行比对、验证签名,并将签署凭证绑定作为必要项。这取代了此前仅做结构性检查的回退机制。时间戳验证器与文档签名提取器共用同一个 ESS issuer-and-serial 验证器,因此两者在凭证绑定解析上不会发生漂移。

归档 DocTimeStamp 覆盖链。 validateArchivalTimestampChain() 会验证一条由受信任 DocTimeStamp 令牌构成、覆盖 PDF 字节范围的链,作为 B-LTA 归档证据。每个令牌的印记都绑定到其实际覆盖的 ByteRange 字节,该链遵循严格的 ETSI 排序,每个令牌的 TSA 链都有信任锚点,且该链必须覆盖文件直到其文件结尾标记。只有完整、具信任锚点且覆盖至 EOF 的链,才能达到完全通过的结果。

凭证策略处理(RFC 5280 §6.1.4)。 路径验证会应用完整的凭证策略处理:节点结构化的策略树、带有 anyPolicy 回退的策略映射,以及 policyConstraints / inhibitAnyPolicy 折叠,并由一个 fail-closed 的策略扩展 DER 读取器支撑。路径处理的状态变量 explicit_policyinhibit_anyPolicy(RFC 5280 §6.1.2)决定是否要求非空的有效策略树;收尾步骤会将有效策略树与 user-initial-policy-set 取交集(RFC 5280 §6.1.4)。在无必要策略且接受 anyPolicy 的情况下,处理不受约束——这是默认值,且与此前行为相同。

验证端接受下列算法集合,并对其外的任何项目以 fail-closed 方式拒绝:不支持的算法会直接导致验证被拒绝,绝不会无声通过。

系列支持备注
RSA(PKCS#1 v1.5)rsaEncryption 搭配 SHA-2,以及 sha*WithRSAEncryption OID接受
ECDSA曲线 P-256、P-384、P-521接受
RSASSA-PSS不支持 → fail-closed
EdDSA不支持 → fail-closed
SHA-3 摘要不支持 → fail-closed
SHA-1弱:使用 SHA-1 通过验证的基本签名会被降级为密码学约束失败,而非通过

验证端通过公开引擎以及 Core / Pki 契约提供。具体的策略类别为内部使用。

类型种类角色
AdESValidationEngineclass验证端的入口点:签名与归档链验证。
AdESValidationEngine::validateArchivalTimestampChain()method验证一条覆盖 PDF 字节范围且受信任的 DocTimeStamp 覆盖链。
ValidationReportresult结构化结果:整体状态加上逐项检查发现。
PathValidatorInterfaceinterface(NextPDF\…\Pki引擎依赖的凭证路径验证 SPI。
PathValidationOptionsvalue object策略处理控制项:requireExplicitPolicyinhibitAnyPolicyinhibitPolicyMappingmaxPolicyFanout
TrustAnchorStoreInterfaceinterface由调用方提供、用于评估凭证链的受信任锚点集合。

归档链方法的签名如下:

public function validateArchivalTimestampChain(
string $pdfBytes,
array $dssData = [],
?TrustAnchorStoreInterface $anchors = null,
): ValidationReport;

只有当 DocTimeStamp 链完整通过验证、具信任锚点,且覆盖文件直到其 EOF 标记时,它才会达到完全通过的结果。

CertificateChainValidator::validate() 接受一组初始策略集合(即 RFC 5280 的 user-initial-policy-set)。默认值为 anyPolicy——不受约束——因此一般凭证链不受影响;若要求非空的有效策略树,请传入明确集合,或设置 requireExplicitPolicy

use NextPDF\Enterprise\Security\Validation\AdESValidationEngine;
$report = $engine->validateArchivalTimestampChain($pdfBytes, [], $trustAnchors);
if ($report->isTotalPassed()) {
// A complete, trust-anchored, EOF-covering DocTimeStamp chain.
}
use NextPDF\Enterprise\Security\Validation\AdESValidationEngine;
use Psr\Log\LoggerInterface;
final readonly class ArchivalEvidenceCheck
{
public function __construct(
private AdESValidationEngine $engine,
private LoggerInterface $logger,
) {}
public function check(string $pdfBytes, TrustAnchorStoreInterface $anchors): bool
{
$report = $this->engine->validateArchivalTimestampChain($pdfBytes, [], $anchors);
foreach ($report->findings as $finding) {
$this->logger->info('archival.finding', [
'check' => $finding->checkId,
'status' => $finding->status->value,
]);
}
// A positive result proves byte-range coverage by a trusted timestamp
// chain — it is one input to your decision, not a legal conclusion.
return $report->isTotalPassed();
}
}

验证端已从结构性和时间性接受转为完整的密码学验证。任何依赖旧有宽松行为的调用方,都应查看这些变更。

  • 对可识别但无法验证的时间戳采取 fail-closed。 此前仅凭结构性与时间性理由通过的 DocTimeStamp 或归档令牌,现在需要完整的密码学验证——签名、message-digest 以及签署凭证绑定。无法通过验证的令牌不再产生正面的存在证明;它会映射为不确定或失败的结果。
  • SHA-1 基本签名会被降级,而非通过。 通过验证但使用 SHA-1 的基本文档签名会被报告为密码学约束失败,而非完全通过。
  • RFC 5280 §6.1.4 凭证策略处理会被强制运行。 一条 explicit_policy 归零且有效策略树为空的凭证链现在会失败——包括由链内 policyConstraints requireExplicitPolicy 驱动的情况。默认且不受约束的凭证链(无必要策略、接受 anyPolicy)不受影响。
  • 构造函数签名变更(BC break)。 AdESValidationEngine::__construct() 现在将其 $chainValidator 参数的类型声明为 Pki\PathValidatorInterface SPI,并以延迟方式默认使用 Pki\CertificateChainValidator::withDefaults()。它此前是具体的 Ltv\CertificateChainValidator。此前注入具体 LTV 验证器的调用方,必须改为注入 Pki SPI 实现。Pki 验证器包装同一个结构性路径引擎,并增加名称约束与策略处理;对符合规范的默认输入而言,它是无操作(no-op)。
  • 不支持的算法 ≠ 无法定论。 RSASSA-PSS、EdDSA 与 SHA-3 会被 fail-closed 拒绝,而非延后处理。若你的签署者使用这些算法,此验证端不会为其返回正面结果。
  • 信任是相对于锚点的。 验证永远相对于你提供的信任锚点存储区。空的或错误的锚点集合会产生不受信任的结果,无论密码学检查是否正确。
  • genTime,而非现在。 TSA 凭证会在令牌的 genTime 进行判定。一个其后已过期的 TSA 凭证,仍可支撑其有效期间内创建的令牌;而在 genTime 时尚未生效的凭证则不能。
  • EOF 覆盖。 归档链必须覆盖文档直到其 EOF 标记。只覆盖文件前缀部分的时间戳,并不能确立整份文档的覆盖。
  • 未被证明已撤销,并不等于状态良好(Good)。 Valid 判定需要一个确切未撤销的状态。如果 OCSP 与 CRL 都返回 Unknown 或 Unavailable,即使签名在密码学上正确、链有效且具信任锚点,也会判定为 Indeterminate——请为签署者凭证提供内嵌的 OCSP/CRL Good 材料,才能达到 Valid

验证在处理进程内、基于所提供的 PDF 字节与内嵌验证材料进行;成本会随链长度与时间戳数量增长。验证期间不进行任何网络往返——撤销与信任材料均取自调用方提供或文档中内嵌的内容。验证具有确定性:相同的输入与相同的信任锚点会产生相同的报告。

  • fail-closed 是默认行为。 每个接受步骤都会拒绝其无法正面验证的材料。这可防止文档声称具有引擎从未确立的有效性。
  • 附加于时间戳之后的内容会被 EOF 覆盖规则击败。 由于每个归档时间戳的印记都绑定到实际的 ByteRange 字节,且该链必须到达 EOF,因此在时间戳之后附加的内容不会被它覆盖,也不会取得其证据效力。
  • 将输入视为恶意。 来自不受信任来源的 PDF 字节、内嵌 CMS 与时间戳令牌,都会由一个严格的定长 DER 读取器解析;该读取器会拒绝格式错误或不定长的编码。

验证在处理进程内、于本机进行,不执行任何网络 I/O。凭证与签名包含主体身份;请对报告及任何提取出的凭证数据应用你自己的保留与最小化控制。

发现项带有检查标识符与状态。某些诊断可能会回显凭证主体名称或序号;在将日志转送至共享接收端之前,请清理或屏蔽这些字段。

请在面向用户的输出中说明这些边界,避免正面结果被过度解读。

  • validateArchivalTimestampChain() 证明的是字节范围覆盖,而非 xref 可达性。 它确立的是:一条受信任的时间戳链以密码学方式覆盖文档的字节范围直到 EOF。它不运行 xref 层级或 startxref 对象可达性分析;这是有意排除在范围之外的。附加于时间戳之后的攻击,是由 EOF 覆盖规则搭配信任锚定所击败,而非由对象图分析击败。
  • 有意排除在范围之外。 此验证端不提供 Evidence Records(RFC 4998 / RFC 6283);不提供 RSASSA-PSS、EdDSA 或 SHA-3 时间戳令牌的验证;不提供受信任清单(TSL)与合格 TSA 集成;也不提供在线 TSA 撤销材料获取。撤销会依据验证器已可取得的材料来评估。
行为参考状态
签名值/时间戳令牌以 DER 编码保存于 /ContentsISO 32000-2 §12.8.1已解析并验证
文档时间戳字典ISO 32000-2 §12.8.5为归档链而读取
接收端重新计算内容摘要;其值必须等于 messageDigest 属性RFC 5652 §5.6 / §5.4已强制运行
TSA 凭证带有单一关键的 id-kp-timeStamping EKURFC 3161 §2.3在 genTime 检查
genTime 为 UTC 创建时刻RFC 3161 §2.4.2作为验证时刻使用
策略处理状态变量(explicit_policyinhibit_anyPolicyRFC 5280 §6.1.2已处理
收尾步骤将有效策略树与 user-initial-policy-set 取交集RFC 5280 §6.1.4已强制运行
针对长期签名的 DSS 项目与文档时间戳ETSI EN 319 142-2 §5.5已验证为归档证据

所有条款均为意译。NextPDF 不复制规范性文本;如需具权威性的表述,请查阅已发布的标准。NextPDF 不作任何 AdES / PAdES 认证声明。 此验证端实现所引用规格描述的密码学检查;它并非经过认证的验证服务,也不产生任何第三方证明。

当 Enterprise FIPS 配置文件启用时,该约束会应用于验证器所接受的摘要与签名算法。验证逻辑——摘要重新计算、签名检查、凭证绑定与路径验证——保持不变。

资产对手风险缓解
时间戳令牌伪造或篡改的令牌虚假的存在证明完整的密码学验证;对任何无法验证者采用 fail-closed
TSA 凭证不受信任的签发者验证器不应主张的表面信任凭证链在 genTime 验证至调用方提供的锚点;不受信任的链永不通过
文档字节附加于时间戳之后内容在未被覆盖的情况下取得时间戳效力印记绑定至实际 ByteRange 字节 + EOF 覆盖规则
弱算法降级为 SHA-1 / 不支持的方案弱签名被读为有效SHA-1 降级;RSASSA-PSS / EdDSA / SHA-3 fail-closed

此验证端是 Enterprise 功能,随 nextpdf/enterprise 套件提供。NextPDF Core 会侦测签名是否存在并生成 B-B / B-T 签名;它不提供此密码学验证端。取得授权

此验证端由 Enterprise 版本闸控(license_feature_flag: enterprise)。它通过 Core 与 Pki 契约接入;公开 API 不会因版本升级而改变。

  • 只有在具备恰好一个 SignerInfo、严格解析的签署属性、已解析的签署者凭证、相符的 message-digest、必要的签署凭证绑定,以及通过验证的 SignerInfo 签名时,CMS 或时间戳令牌才会被接受。
  • TSA 凭证会在令牌的 genTime 进行验证:单一关键的 id-kp-timeStamping EKU、有效期间、具信任锚点的凭证链,以及撤销。
  • 一个 Valid 判定还额外要求确切未撤销的状态——至少一个具权威性的 Good(一个经验证为良好的 OCSP 回应,或一份未过期且未列出该序号的最新 CRL)。如果状态只是未被证明已撤销,且 OCSP 与 CRL 皆为 Unknown 或 Unavailable,则会判定为 Indeterminate,绝不会是 Valid(ETSI EN 319 102-1:撤销状态无法取得 → INDETERMINATE)。由于 CRL 回退路径仅证明清单的新鲜度,而非逐序号的撤销状态,因此一条仅有 CRL、缺少 Good OCSP 的链通常为 Indeterminate
  • validateArchivalTimestampChain() 只有针对完整、具信任锚点且覆盖至 EOF 的 DocTimeStamp 链才会达到完全通过的结果;它证明的是字节范围覆盖,而非 xref 可达性。
  • 凭证策略处理遵循 RFC 5280 §6.1.4;默认不受约束的凭证链不受影响。
  • 支持的算法为 RSA(PKCS#1 v1.5 搭配 SHA-2)与 ECDSA(P-256/384/521);RSASSA-PSS、EdDSA 与 SHA-3 采 fail-closed;SHA-1 会被降级。

此公开页面仅描述外部可观察的验证端行为。它通过受支持的接口点名公开引擎、Pki / 信任锚点契约,以及 validateArchivalTimestampChain() 方法。具体的 DER、CMS、策略处理器与路径验证器内部,位于受 NDA 约束的深度参考中。

NextPDF Core 会侦测签名是否存在并生成 B-B / B-T 签名,但它不以密码学方式验证 CMS 或时间戳令牌、不验证归档链,也不运行 RFC 5280 §6.1.4 策略处理。仅部署 Core 的环境没有对等的验证端;请参阅 Security / Signing (Core)

NextPDF Pro 增加了签署策略与电子发票处理,但不提供此密码学验证端;归档链验证与凭证策略处理仅在 nextpdf/enterprise 中提供。

此验证端按行为层级描述。严格 DER 堆栈、CMS 解析器、策略处理器与路径验证器内部,超出公开接口范围,且不会在此重述。

验证取决于信任锚点存储区,以及调用方提供或文档中内嵌的任何撤销材料。NextPDF Enterprise 会评估这些材料;它不运营信任清单、TSA 或撤销服务。操作者负责锚点选择与内嵌撤销材料的新鲜度。

此页面标记为 export_control_class: legal-review-required;它涉及密码学验证。在设置 publish 旗标之前,须取得法务签核。正面的验证结果是关于文档签名与时间戳的密码学陈述——它不是法律意见、不是 eIDAS 合格性判定,也不是认证。NextPDF 不作任何 AdES / PAdES 认证声明。 关于你的法规义务,请咨询你自己的合规与法律顾问。