一文讲清楚PDF数字签名的基本原理

1,362 阅读7分钟

Acrobat PDF的数字签名实现原理可访问Adobe的官方说明,这里摘取该文档的关键部分,与各位读者一起详细探讨下基于PDF实现文档数字签名及验签的基本原理。

1. PKI公钥基础设施体系

PDF的数字签名是基于公钥基础设施(public key infrastructures ,PKI)体系相关的标准设计,包含了数字证书的颁发者、用户、管理员以及在整个流程中使用的硬件(如加密设备HSM)和软件(如签名管理系统),如图1所示。 image.png

图1 数字签名流程中常见的PKI元素

基于X509.v3标准的数字证书的格式: image.png 图2  X.509 v3的数字证书格式

关于数字证书的一些格式:

  • DER-encoded certificate: .cer, .crt,用于存放证书,它是2进制形式存放的,不含私钥
  • PEM-encoded message: .pem ,跟crt/cer的区别是它以Ascii来表示
  • PKCS#12 Personal Information Exchange: .pfx, .p12 ,用于存放个人证书/私钥,他通常包含保护密码,2进制方式
  • PKCS#10 Certification Request: .p10 ,证书请求
  • PKCS#7 cert request response: .p7r ,CA对证书请求的回复,只用于导入
  • PKCS#7 binary message: .p7b ,以树状展示证书链(certificate chain),同时也支持单个证书,不含私钥。

在PKI体系中,最核心的是用户的身份认证,包含了用户的身份校验以及为其颁发数字证书,一般由国内或者国际上可信任的权威CA机构完成。一些关键节点描述如下:

(1)根证书(CA):顶级权威CA机构的CA证书,一般是自签名或者其他顶级CA签名的CA证书。通常是位于证书链顶端的根证书。

image.png

图2-1 根证书示例1

image.png

图2-2 根证书示例2

(2)中间证书ICA:由顶级CA授权的二级CA机构(或者顶级CA自己也可以兼任),主要用于给普通用户颁发数字证书,该证书不是自签名的。 image.png

image.png

图2-3 中间证书示例1

image.png

图2-4 中间证书示例

说明:CA证书(一般特指根证书和中间证书)一定有示例中的特征,但是有这些特征的未必能代表CA机构

(3)数字证书ID(Digital ID):二级CA颁发给普通用户的数字证书,基于X.509 v3标准,一般与个人或者企业关联。包含公钥证书、私钥和其他数据。其密钥用途一般为数字签名,加密密钥等,而不会包含CA根证书或中间证书的作为CA机构的密钥用途,更不会在“基本限制”中标记为CA。

image.png

image.png

图2-5 数字证书示例

image.png

图2-6 数字证书示例

(4)公钥证书(Public Key Certificate):包含公/私钥对的数字公钥部分以及用于定义证书所有者、有效期和相关扩展熟悉的文件。

(5)私钥(Private Key):PKI系统中的密钥,用于验证传入消息和对传出消息进行签名。

(6)证书吊销列表(CRL):存储在本地的已吊销证书的列表,一般由二级CA提供。

(7)时间戳服务:签名过程中需要对消息进行时间戳签名的服务。

2. PDF数字签名的组成部分

根据PDF参考文档定义的格式,一个带有数字签名的PDF文档结构如图3所示,在PDF中,签名信息包含在签名字典(signature dictionary)中,签名字典与其他字典可以互相引用,字典中的每一个属性就决定了签名的性质和特性等,在我们的业务中,就是利用这些属性的扩展来设计我们的电子签名系统。

image.png

图3  包含数字签名的PDF文档结构

在PDF的签名字典中,有两个关键的属性,一个是ByteRange,一个是Contents,下面就这两块进行详细的说明,以便大家更清楚的理解PDF签名的原理和数据格式。

(1)ByteRange

计算Hash值的字节范围,是一个由4个数字组成的数组,相当于两对起止位置,每一对中的第一个数字是在文件中计算Hash值的字节流的起始偏移量(从0开始),第二个数字是流的长度。文档Hash值计算,就是使用ByteRange值指定的字节,使用哈希算法(如SHA-256)进行计算。在Acrobat计算文档Hash值的过程中,总是对整个PDF进行计算,即从字节0开始,以物理文件的最后一个字节结束,但不包括签名值字节。实际的签名值存储在第一个序列结束和第二个序列开始之间的/Contents中。如图4所示,计算了从0开始的839字节和从960开始的1200字节的Hash值。

image.png

图4  ByteRange和签名值

在PDF中,任何通过修改文件(如再次签名)来修改文档都会使现有的签名无效。主要原因是在验证时计算的哈希值与在签名时创建的哈希值不匹配。

PDF通过支持增量更新的方式来解决多个签名的问题。方法是在增量更新部分中将修改信息添加到未见的末尾,不需要对早期版本的字节进行任何更改。具体的实现方式如图5所示:

image.png

图5  多个签名和增量更新

(2)Contents

PDF支持将签名嵌入到文档本身,如上所述,计算出来需要签名的ByteRange范围内的文档内容Hash值,使用用户私钥对该值进行签名,将签名结果及证书信息组装成P7格式数据(签名值),存放在Contents中。签名值(如图6所示)一般包含的内容有:

  • 签名者的公钥证书:签名使用的公钥证书(X.509格式),包含证书链信息。
  • 签名消息摘要:使用用户私钥对文档Hash值进行签名的结果。
  • 时间戳:时间戳服务及及其数字签名。
  • 其他信息。

image.png

图6  数字证书与PDF签名

3. PDF如何完成数字签名

(1)pdf文档签名的流程

PDF创建签名的工作流程如图7所示,主要步骤如下所述:

① 打开待签署pdf文档,调用签名处理程序。

② 创建签名外观(Signature apprearance,包括图片、文本、字体设置、位置信息等等),合成到文档中。

③ 计算待签名区域ByteRange,使用摘要算法(如SHA256)对待签名区域内容计算Hash值。

④ 调用用户数字证书,确定签名算法,使用证书私钥对Hash值进行加密,得到加密密文。

⑤ 对私钥加密结果使用时间戳进行签名,得到时间戳签名结果。

⑥ 按照指定格式(PKCS7)对以上签名结果进行组装,生成P7数据。

将P7数据合成到到签名字典的/Contents中。签名完成。

image.png

图7 PDF文档签名创建流程

(2)已签名pdf验签流程

如图8所示,关键步骤如下:

文档数字签名-pdf验签流程.drawio.png

图8 PDF已签名文档验签流程

① 检查Hash签名值是否有效,根据ByteRange计算签名区域的Hash值,读取签名值中的签名结果,使用证书公钥进行解密,得到证书加密前的Hash值,对两个Hash值进行比对,如果不一致,则文档被篡改。

② 检查嵌入的时间戳是否有效,原理同上。

③ 检查签名时使用的证书有效性(是否已生效且未过期)。

④ 根据CRL检查签名时使用的证书吊销状态。

⑤ 检查中级证书及根证书的有效性及吊销状态。

⑥ 检查中级证书及根证书是否来自可信任源。