PDF签名系列(2):PDF的签名值到底存在哪里?

46 篇文章 6 订阅

来源:PDF签名系列(2):PDF的签名值到底存在哪里? - 知乎

研究过PDF签名的同学应该见过下面这张图, 来自ADOBE的文档Acrobat_DigitalSignatures_in_PDF.pdf

preview

PDF被签名的内容是整个文档除去signature dictionary里/Contents下面的内容. 签过名的哈希值再连同其他一些信息一起写进/Contents里. 也就是说/Contents内容以外的部分一旦被修改, 签名就无法验证通过了.

但是这张图容易误导我们的地方是, 我们会以为签名值就是一个由证书, 签名哈希, 时间戳组成的list. 而且"Signature value"也容易与SignerInfo里的Signature Value混淆.

其实, /Contents下面的真正内容是一个DER编码的PKCS#7数据对象, 通常我们称它为一个PKCS#7 container.

所以下面稍微详细解析一下PKCS#7格式, 它跟CMS几乎是一样的, 可以把二者看成一个统一的概念. PKCS#7需要符合RFC3852/RFC5652的标准.

CMS是加密消息语法, 它并不是一个专为数字签名而定制的标准, 它定义了一个对象ContentInfo, 包含Content Type和Content:

 

preview

Content Type有6种:

  • Data,
  • Signed-data,
  • Enveloped-data,
  • Digested-data,
  • Encrypted-data
  • Authenticated-data

 对于数字签名来说, 属于Signed-data类型. ContentInfo里的content是一个SignedData类型:

preview

SignedData包含一个EncapsulatedContentInfo, 存的是待签名的原文内容. 我们已经知道,对原文的签名其实是对原文摘要的加密, 如果把原文内容放进这里, 签名值有可能会变得很大, 签完名的文档的大小就翻了倍. 一般来说, 会把EncapsulatedContentInfo空着, 这就是detached signature. 这跟通常意义上的跟Embedded signature相对的detached signature不是一个概念. Embedded Signature的意思是把一个文档的签名值嵌入文档中成为一个文件, 相对的, detached signature是把文档的签名值和文档分开保存. 对于CMS中的detached signature的概念则是另外一回事, 明白了这个也就明白了, SubFilter里的值为adbe.pkcs7.detached的原因.

SignedData里还包含了SignerInfos, 可以为每个签名者创建一个独立的SignerInfo, 也就是说CMS是支持多人平行签名(Parallel Signature)的. 但是PDF只支持增量签名(Incremental Signature), 也就是后一个签名版本是前一个签完名的文档加上文档的更新内容. 见下图

 

具体可以参考Acrobat_DigitalSignatures_in_PDF.pdf.

SignerInfo的结构如下:

preview

 其中SignerIdentifier是签名者的证书信息, DigestAlgorithmIdentifier是该签名者使用的摘要算法标识, SignatureAlgorithmIdentifier是该签名者使用的签名算法, SignedAttributes和UnsignedAttributes是一些属性, SignatureValue就是真正的签名值了!

SignedAttributes是需要签名的属性, 是Optional的. 如果为空, 那么SignatureValue就直接是原文内容的签名值了. 如果SignedAttributes不为空, 那么至少要包含两个Attibutes: 

也就是说至少要把原文数据的content type和消息摘要包含进去, 然后加上别的需要签名的属性, 例如revocation information, 对SignedAttributes做哈希和加密, 产生的签名值作为SignatureValue. 所以这种情况下是要做两次哈希的, 第一次是原文的哈希, 第二次是对SignedAttributes做哈希.

至此, 我们从PDF的signature dictionary结构深入到PKCS#7结构里的找到了签名值的位置. 下面打算继续研究MIME, ESS等内容以及它们与CMS的关系.

补充:

ESS - The ESS signing-certificate-v2 attribute是第三个必须要包含在Signed attributes中的属性.

S/MIME - 邮件中的CMS object

参考文档:

Acrobat_DigitalSignatures_in_PDF.pdf

RFC5652-Cryptographic Message Syntax (CMS)

PDF Signature digest

Message digest of pdf in digital signature

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在PDF文件中添加签名图片和日期,可以使用 pypdf2 库中的以下步骤: 1. 打开原始 PDF 文件并创建一个新的 PDF 文件对象。 2. 从原始 PDF 文件中获取需要签名的页面并将其添加到新的 PDF 文件对象中。 3. 使用 Pillow 库中的 Image 模块打开签名图片文件。 4. 将签名图片文件添加到新的 PDF 文件对象中的需要签名的位置。 5. 使用 datetime 模块获取当前日期时间。 6. 将当前日期时间添加到新的 PDF 文件对象中的需要签名的位置。 7. 保新的 PDF 文件对象并关闭原始 PDF 文件对象。 这是一个示例代码,可以根据自己的需求进行修改: ```python from datetime import datetime from PyPDF2 import PdfFileReader, PdfFileWriter from PIL import Image # 打开原始 PDF 文件和创建新的 PDF 文件对象 with open('original.pdf', 'rb') as file: pdf_reader = PdfFileReader(file) pdf_writer = PdfFileWriter() # 获取需要签名的页面并将其添加到新的 PDF 文件对象中 page = pdf_reader.getPage(0) pdf_writer.addPage(page) # 打开签名图片文件并将其添加到新的 PDF 文件对象中的需要签名的位置 signature = Image.open('signature.png') signature_page = pdf_writer.getPage(0) signature_page.mergeScaledTranslatedPage(signature_page, signature.width, signature.height, -50, 50) # 将当前日期时间添加到新的 PDF 文件对象中的需要签名的位置 date = datetime.now().strftime("%Y-%m-%d %H:%M:%S") signature_page.addText(date, 50, 50) # 保新的 PDF 文件对象并关闭原始 PDF 文件对象 with open('signed.pdf', 'wb') as output: pdf_writer.write(output) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值