数字签名中pdf的消息摘要

时间:2015-02-09 10:52:57

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

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

  • 获得了' / Content'的价值来自pdf的节点(使用PyPDF2)。这是der编码的PKCS#7证书。

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

  • PDF规范快照: - snap

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

1 个答案:

答案 0 :(得分:1)

(这更多是评论而不是答案。由于评论的大小和格式限制,我仍然把它写进了一个答案。)

PDF中的签名

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

Figure 3 Digital ID and a signed PDF document

但这仅仅是一个草图,并且字面上解释它可能会留下错误的印象,即签名词典中内容条目的值类似于包含“证书”的列表, “签名消息摘要”和“时间戳”。此外,调用此列表的“签名值”也可能会混淆,因为该名称也用于内容的一小部分,请参阅下文。

指定实际内容(参见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的结构......正如已经提到的那样,上面调用整个签名容器“Signature value”的草图可能会混淆,因为这里已经是一个名为的实体那样的。)

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

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

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

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

    如果签名算法基于DSA或EC DSA,则根本无法检索摘要值。这些算法只允许您检查您提供的摘要值(例如,在您检索文档时已经散列了文档的带符号字节范围)是否是最初签名的。

  • 在使用SignerInfo的{​​{1}}个实例的更常见情况下,您必须在这些SignedAttributes中搜索由

    标识的消息摘要属性
    SignedAttributes

正如评论中已经提到的,我无法解释如何使用Python或openssl向下钻取。您将需要一些知道这些特定ASN.1结构或ASN.1结构的工具。