Acrobat PDF的数字签名实现原理可访问Adobe的官方说明,这里摘取该文档的关键部分,与各位读者一起详细探讨下基于PDF实现文档数字签名及验签的基本原理。
1. PKI公钥基础设施体系
PDF的数字签名是基于公钥基础设施(public key infrastructures ,PKI)体系相关的标准设计,包含了数字证书的颁发者、用户、管理员以及在整个流程中使用的硬件(如加密设备HSM)和软件(如签名管理系统),如图1所示。
图1 数字签名流程中常见的PKI元素
基于X509.v3标准的数字证书的格式:
图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证书。通常是位于证书链顶端的根证书。
图2-1 根证书示例1
图2-2 根证书示例2
(2)中间证书ICA:由顶级CA授权的二级CA机构(或者顶级CA自己也可以兼任),主要用于给普通用户颁发数字证书,该证书不是自签名的。
图2-3 中间证书示例1
图2-4 中间证书示例
说明:CA证书(一般特指根证书和中间证书)一定有示例中的特征,但是有这些特征的未必能代表CA机构
(3)数字证书ID(Digital ID):二级CA颁发给普通用户的数字证书,基于X.509 v3标准,一般与个人或者企业关联。包含公钥证书、私钥和其他数据。其密钥用途一般为数字签名,加密密钥等,而不会包含CA根证书或中间证书的作为CA机构的密钥用途,更不会在“基本限制”中标记为CA。
图2-5 数字证书示例
图2-6 数字证书示例
(4)公钥证书(Public Key Certificate):包含公/私钥对的数字公钥部分以及用于定义证书所有者、有效期和相关扩展熟悉的文件。
(5)私钥(Private Key):PKI系统中的密钥,用于验证传入消息和对传出消息进行签名。
(6)证书吊销列表(CRL):存储在本地的已吊销证书的列表,一般由二级CA提供。
(7)时间戳服务:签名过程中需要对消息进行时间戳签名的服务。
2. PDF数字签名的组成部分
根据PDF参考文档定义的格式,一个带有数字签名的PDF文档结构如图3所示,在PDF中,签名信息包含在签名字典(signature dictionary)中,签名字典与其他字典可以互相引用,字典中的每一个属性就决定了签名的性质和特性等,在我们的业务中,就是利用这些属性的扩展来设计我们的电子签名系统。
图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值。
图4 ByteRange和签名值
在PDF中,任何通过修改文件(如再次签名)来修改文档都会使现有的签名无效。主要原因是在验证时计算的哈希值与在签名时创建的哈希值不匹配。
PDF通过支持增量更新的方式来解决多个签名的问题。方法是在增量更新部分中将修改信息添加到未见的末尾,不需要对早期版本的字节进行任何更改。具体的实现方式如图5所示:
图5 多个签名和增量更新
(2)Contents
PDF支持将签名嵌入到文档本身,如上所述,计算出来需要签名的ByteRange范围内的文档内容Hash值,使用用户私钥对该值进行签名,将签名结果及证书信息组装成P7格式数据(签名值),存放在Contents中。签名值(如图6所示)一般包含的内容有:
- 签名者的公钥证书:签名使用的公钥证书(X.509格式),包含证书链信息。
- 签名消息摘要:使用用户私钥对文档Hash值进行签名的结果。
- 时间戳:时间戳服务及及其数字签名。
- 其他信息。
图6 数字证书与PDF签名
3. PDF如何完成数字签名
(1)pdf文档签名的流程
PDF创建签名的工作流程如图7所示,主要步骤如下所述:
① 打开待签署pdf文档,调用签名处理程序。
② 创建签名外观(Signature apprearance,包括图片、文本、字体设置、位置信息等等),合成到文档中。
③ 计算待签名区域ByteRange,使用摘要算法(如SHA256)对待签名区域内容计算Hash值。
④ 调用用户数字证书,确定签名算法,使用证书私钥对Hash值进行加密,得到加密密文。
⑤ 对私钥加密结果使用时间戳进行签名,得到时间戳签名结果。
⑥ 按照指定格式(PKCS7)对以上签名结果进行组装,生成P7数据。
将P7数据合成到到签名字典的/Contents中。签名完成。
图7 PDF文档签名创建流程
(2)已签名pdf验签流程
如图8所示,关键步骤如下:
图8 PDF已签名文档验签流程
① 检查Hash签名值是否有效,根据ByteRange计算签名区域的Hash值,读取签名值中的签名结果,使用证书公钥进行解密,得到证书加密前的Hash值,对两个Hash值进行比对,如果不一致,则文档被篡改。
② 检查嵌入的时间戳是否有效,原理同上。
③ 检查签名时使用的证书有效性(是否已生效且未过期)。
④ 根据CRL检查签名时使用的证书吊销状态。
⑤ 检查中级证书及根证书的有效性及吊销状态。
⑥ 检查中级证书及根证书是否来自可信任源。