【问题标题】:How to compute message-digest in a SignerInfo?如何在 SignerInfo 中计算消息摘要?
【发布时间】:2025-12-06 05:10:01
【问题描述】:

我正在尝试生成启用 LTV 的 pdf。我生成了一个包含所有必需属性的 pkcs7 对象,包括 signerInfo 对象。生成的签名有效,但未启用 LTV。根据 PDF 参考手册,我需要包含验证信息(CRLS 或 OCSP ...),并且基于 rfc3852,此内容进入 signedAttributes 对象,并且它必须包含内容类型属性和消息摘要属性。我的问题是如何计算消息摘要值,是否需要在 pdf 内容旁边签名?

注意:包含 CRL 的 adbe-revocationInfoArchival 对象似乎是正确的,因为 acrobat 直接从文件中读取吊销信息。我似乎遇到的唯一问题是 signedAttrs 对象中包含的消息摘要和/或未正确计算签名值。 RFC 不太清楚该消息摘要应该是什么,或者它是否应该包含在将使用签名者私钥签名的摘要中。

【问题讨论】:

  • “我的问题是如何计算消息摘要值” - pdf 的有符号字节范围的哈希值 - “是否有必要在 pdf 内容旁边签名?” - 这是什么意思?您可以通过将其散列作为消息摘要值来签署 pdf 内容。 “我似乎遇到的唯一问题” - 实际上你的问题似乎表明可能还有其他错误。
  • 不是pdf文档的消息摘要,我说的是签名属性字段中的消息摘要。我只是签署 pdf 没有问题,我想做的是在 PKCS7 结构中添加 CRL,这样签名就可以启用 LTV
  • “不是 pdf 文档的消息摘要,我说的是签名属性字段中的消息摘要。” - 是的,你说的是消息-digest 签名属性。该属性的值是 PDF 的带符号字节范围的哈希
  • 所以这些属性没有签名? rfc 声明它们是,因此名称为“signedAttr”。我尝试使用 pdf 摘要(与正确签名和验证的相同),当我打开 pdf 时,没有 pdf 阅读器可以验证签名,就像新添加的属性更改了应该签名的完整消息摘要一样. Here 是另一个比 rfc 更具可读性的来源
  • “那么这些属性没有签名?” - 为什么这些属性应该没有签名

标签: pdf cryptography digital-signature pkcs#7


【解决方案1】:

在 cmets 中反复讨论问题后,我仍然不确定您需要什么信息,所以这里有一些关于 PDF 签名的非平凡 CMS 签名容器的结构和内容的一般想法.

规格

不过,首先,关于使用规范的一些话。您提到了PDF 参考手册rfc3852。两者实际上都不再是最先进的了,但有趣的是比另一个少一个。

  • 最初,Adobe PDF References for PDF 最高 1.7 是要查看的文档。不幸的是,Adobe 认为这些参考文献本质上不规范,即如果当前参考文献和当前 Acrobat 版本在某些方面存在分歧,则程序是正确的,而不是参考文献!

    最新的 Adob​​e PDF 参考(适用于 PDF 1.7)参考了 RFC 2315 的签名容器结构。

  • 然后,Adobe 将 PDF 格式的权威移交给了国际标准化组织 (ISO),该组织于 2008 年发布了第一个规范性 PDF 规范 ISO 32000-1,该规范在内容上与上一个 PDF 参考非常相似,但采用了RFC'ish 语言。

    ISO 32000-1 参考 RFC 3852 和 RFC 2315 的签名容器结构。这很奇怪,但剩下的 RFC 2315 参考很可能是疏忽。

  • 在 2017 年,ISO 发布了 PDF 2.0 的 PDF 规范 ISO 32000-2,并在签名方面进行了一些相关更改。

    ISO 32000-2 参考 RFC 5652 的 adbe.pkcs7.detached 签名的签名容器结构和 ETSI EN 319 122 的 ETSI 签名容器的结构.CAdES.detached 签名。

  • 2020 年,ISO 更新了 ISO 32000-2 并做出了多项说明;签名容器规范的引用保持不变。

因此,目前您应该查看 ISO 32000-2:2020 和 RFC 5652。

CMS 签名容器

你在迟到的评论中说

我想知道如何将这些属性添加到要签名的最终摘要中。我正在使用 SHA 来消化 pdf,然后使用 rsa 私钥对其进行签名并构建 pkcs7 结构,包括证书链、签名消息和时间戳作为未签名属性。

这个过程只能创建简单的签名容器没有签名的属性,因为只有在这些简单的容器中,文档哈希才被直接签名。但是你要添加的adbe-revocationInfoArchival属性必须是签名属性,一旦涉及到签名属性,就不再直接对文档哈希值进行签名了。

CMS 签名容器包含一个 SignedData 对象,其中恰好有一个 SignerInfo 对象。 SignerInfo 对象定义为

  SignerInfo ::= SEQUENCE {
    version CMSVersion,
    sid SignerIdentifier,
    digestAlgorithm DigestAlgorithmIdentifier,
    signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
    signatureAlgorithm SignatureAlgorithmIdentifier,
    signature SignatureValue,
    unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }

(RFC 5652 第 5.3 节。“SignerInfo 类型”)

在您的工作代码创建的签名容器中,OPTIONAL signedAttrs 不存在,并且立即为文档哈希计算 signature 值。

不过,一旦有签名属性,OPTIONAL signedAttrs 就不再缺席,而是 SETAttribute 实例,包括至少

  • 一个以 id-data 为值的 content-type 属性,
  • 一个 message-digest 属性,以待签名 PDF 字节范围的摘要值作为值,
  • 在你的例子中是一个 adbe-revocationInfoArchival 属性,其值为撤销信息。

在这种情况下signature不再立即为文档哈希计算,而是代替signedAttrs 的哈希值 em>!

更准确地说,它是针对其完整DER编码的哈希值计算的,而不是使用IMPLICIT [0]标签,而是使用EXPLICIT SET OF 标记。

因此,在使用 SHA 消化 pdf 之后,您而不是 使用 rsa 私钥对其进行签名并构建 pkcs7 结构继续

  • 至少使用上面列举的属性条目构建签名属性集,对该集进行 DER 编码并对其进行哈希处理,
  • 使用您的私钥对已签名属性的哈希值进行签名,并且
  • 使用这些签名属性和此签名值以及证书链构建 CMS 签名容器结构。

您还可以添加签名时间戳。

【讨论】:

  • Ohhhh,所以我不需要直接签署 pdf 的散列值,我需要签署包含 pdf 的散列值 和 crls 的 signedAttrs 的散列值对?我试图同时签署 pdf 摘要和 signedAttrs 摘要
  • 刚刚尝试过并获得了启用 LTV 的验证 pdf。非常感谢!
  • “哦,所以不是...” - 正确,文档哈希然后是间接签名的。 “刚刚尝试过,并获得了启用 LTV 的验证 pdf。” - 太好了!