【问题标题】:Message digest of pdf in digital signature数字签名中pdf的消息摘要
【发布时间】:2015-04-09 02:10:48
【问题描述】:

我想手动验证签名 pdf 的完整性。我已经能够到达:-

  • 从 pdf 中获取“/Content”节点的值(使用 PyPDF2)。这是der 编码的 PKCS#7 证书。

现在根据pdf specifications,pdf 数据的消息摘要与证书一起存储在/Content 节点中。尝试了很多,但我无法获得最终将与散列 pdf 内容(由 /ByteRange 指定)进行比较的摘要值。

  • PDF 规格快照:-

不明白write signature object data into the dictionary 的最后一部分。这个写入实际发生在哪里,我如何提取消息摘要?

【问题讨论】:

  • @BrunoLowagie...对不起。将编辑问题。这是 der 编码的 PKCS#7。
  • 从 pdf 中获取 '/Content' 节点的值(使用 PyPDF2)。这是一个 der 编码的 PKCS#7 证书 - A 它应该是一个 PKCS#7 / CMS 签名容器(只要 SubFilter 是 ETSI.CAdES.detachedadbe.pkcs7.detachedadbe.pkcs7.sha1),可能包含 证书作为额外的有效负载;更重要的部分是 SignerInfo,不过... B 虽然根据规范,此签名对象应进行 DER 编码,但在野外有许多带有签名对象的 PDF,其外层仅经过 BER 编码.
  • @mkl 感谢您的意见。是的,这里的 /Subfilter 是 adbe.pkcs7.detached。现在我声明的原因是:- **A)**我得到了 '/Content' 节点的内容并将其写入文件--> 使用 openssl pkcs7 命令行实用程序将其转换为可读的 pem。我对使用加密和数字证书很陌生。您能帮我弄清楚如何从证书中提取此消息摘要并将其用于手动检查吗? **B)**外层->你的意思是容器吗?
  • 你能帮我弄清楚 - 不幸的是,我几乎没有使用过 openssl,而且我根本没有任何 python 经验。我所能做的就是解释低级对象。 如何从证书中提取此消息摘要并将其用于手动检查 - 但您不想从证书中提取消息摘要。您想从 签名容器 中提取它。 外层->你的意思是容器 - 是的。但很可能无论如何您都不会感知到不同的编码,大多数工具都可以处理。
  • @mkl 好的,谢谢。这就说得通了。事实上,我也在雕刻一些低级细节。你是对的,我需要从签名容器中提取摘要(实际上我在阅读 pdf 规范时感到困惑)。无论如何,你能帮我弄清楚这个签名容器在哪里以及如何解析它来获取消息摘要。到目前为止,我认为消息摘要嵌入在数字签名中的某处(正如我从 pdf 规范中理解的那样)。

标签: python pdf digital-signature digital-certificate pem


【解决方案1】:

(这更像是一个评论而不是一个答案。由于 cmets 的大小和格式限制,我还是把它放在一个答案中。)

PDF 中的签名

prior question 中,OP 已经插入了一个草图,说明在 SubFilter ETSI.CAdES.detachedadbe 的情况下嵌入在 PDF 中的签名。 pkcs7.detached,或adbe.pkcs7.sha1

但这只是一个草图,如果按字面意思解释它可能会留下错误的印象,即签名字典中 Contents 条目的值类似于包含“证书”的列表, “签名消息摘要”和“时间戳”。此外,将此列表称为“签名值”也会造成混淆,因为该名称也用于一小部分内容,见下文。

实际内容被指定(参见this document)为:

当使用 PKCS#7 签名时,Contents 的值应是包含签名的 DER 编码的 PKCS#7 二进制数据对象。 PKCS#7 对象应符合 RFC3852 加密消息语法。

(顺便说一句:虽然这里的规范要求对数据对象进行 DER 编码,但在野外有许多签名的 PDF,它们对整个对象使用一些不太严格的 BER 编码,而 DER 仅用于部分RFC3852 也要求进行 DER 编码。)

PKCS#7 二进制数据对象

包含符合 RFC3852 的签名的 PKCS#7 二进制数据对象更准确地说是具有 SignedData 内容的 ContentInfo 对象,通常命名为一个“签名容器”。

根据RFC 3852

CMS 将内容类型标识符与内容相关联。这 语法必须具有 ASN.1 类型的 ContentInfo:

  ContentInfo ::= SEQUENCE {
    contentType ContentType,
    content [0] EXPLICIT ANY DEFINED BY contentType }

签名数据内容类型应具有 ASN.1 类型 SignedData:

  SignedData ::= SEQUENCE {
    version CMSVersion,
    digestAlgorithms DigestAlgorithmIdentifiers,
    encapContentInfo EncapsulatedContentInfo,
    certificates [0] IMPLICIT CertificateSet OPTIONAL,
    crls [1] IMPLICIT RevocationInfoChoices OPTIONAL,
    signerInfos SignerInfos }

在这里您可以看到可选集合certificates,其中通常至少包含签名者证书,并且通常还包含其颁发者证书链。这是上面草图中的“证书”。

您还会看到包含实际签名信息的 signerInfos 结构:

  SignerInfos ::= SET OF SignerInfo

每个签名者的信息以 SignerInfo 类型表示:

  SignerInfo ::= SEQUENCE {
    version CMSVersion,
    sid SignerIdentifier,
    digestAlgorithm DigestAlgorithmIdentifier,
    signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
    signatureAlgorithm SignatureAlgorithmIdentifier,
    signature SignatureValue,
    unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
  SignedAttributes ::= SET SIZE (1..MAX) OF Attribute
  Attribute ::= SEQUENCE {
    attrType OBJECT IDENTIFIER,
    attrValues SET OF AttributeValue }

(在这里您可以看到 RFC 调用 SignatureValue... 的结构,如前所述,上面调用整个签名容器“签名值”的草图可能会让人感到困惑,因为这里已经是一个名为这样的类型的实体.)

您正在查看 adbe.pkcs7.detached 类型 PDF 签名的已签名 PDF 字节范围的消息摘要。其实有两种可能:

  • 在最简单的SignerInfo 实例的极少数情况下,没有SignedAttributes。在这种情况下,SignatureValue 是立即应用于签名字节范围的签名算法的值。

如果签名算法基于 RSA,您可以通过使用签名者的公钥(从他的证书中)解码值并从解码的 DigestInfo 对象中提取摘要来检索文档摘要值。

    DigestInfo ::= SEQUENCE {
      digestAlgorithm DigestAlgorithmIdentifier,
      digest Digest }

如果签名算法基于 DSA 或 EC DSA,则根本无法检索摘要值。这些算法只允许您检查您提供的摘要值(例如,在您检索文档时对文档的签名字节范围进行哈希处理)是否是最初签名的。

  • 在更常见的SignerInfo 实例与SignedAttributes 的情况下,您必须在这些SignedAttributes 中搜索由标识的消息摘要属性
 id-messageDigest OBJECT IDENTIFIER ::= { iso(1) member-body(2)
        us(840) rsadsi(113549) pkcs(1) pkcs9(9) 4 }

不过,正如 cmets 中已经提到的,我无法解释如何使用 Python 或 openssl 在此处进行深入研究。您将需要一些了解这些特定 ASN.1 结构或一般 ASN.1 结构的工具。

【讨论】:

  • 精湛的解释。感谢您的详细分析。这对我来说是一种答案......一旦我真正完成了所有分析,就会更新。
  • 使用 openssl 读取提取的 PKCS#7:openssl asn1parse -in signature.bin -inform der 分别为 openssl pkcs7 -in signedHashCert.bin -inform der -text
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-14
  • 2014-09-21
  • 1970-01-01
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多