最近几个月干了不少 PDF 相关的活,趁着这两天不忙,记录一下相关的知识点。
PDF是 Portable Document Format的简称,翻译过来是“可携带文档格式”,由 Adobe于1992年创建。其格式特点是,与操作系统平台无关,在任意平台上都可以保持相同的渲染效果。
至于这个平台无关嘛……倒不如说是格式简单,各平台都遵循同一标准,再加上标准的公开,自然就做到了平台无关性。
发展史
PDF 从创建之后,一直是 Adobe 公司的专有格式,直到2008年,才成为正式的ISO(ISO 32000)标准。
虽然 PDF 文件已经成为了标准, 但 Adobe 作为 PDF 的鼻祖,还是弄了些私有的功能,比如 XFA(Adobe PDF 表单),这玩意就不属于 ISO 32000 PDF标准。
国产格式 - OFD
和 PDF 类似的,还有 OFD (Open Fixed-layout Documents)格式,算是“国产PDF”标准,由中国国家标准化管理委员会于2016年正式发布。
和 PDF 格式相比,OFD 格式更简单,更易于实现,而且支持国密,不过目前使用的很少。
字体
常见的 Office 格式里,字体默认都是非内嵌的,非内嵌字体可以避免重复存储相同的字体,只需要渲染设备上安装对应字体就行;但劣势也很明显,如果客户设备上没有对应的字体,就会导致无法渲染,使用替代字体的话,又会影响渲染效果。
而 PDF 在字体的处理上和 Office 有所不同,PDF 默认使用内嵌字体的方式,而且还是内嵌字体的子集 - 只把文件中使用的字符字体给嵌入到PDF文件中,并不会将整个字体库嵌入。这样一来,即时内嵌了字体,也不会过多的增加文件大小。
字体加密
某些文档为了数据安全,提供 PDF 格式的资料供查阅,但又不想让用户随意复制文字。
此时 PDF 内嵌字体的好处就体现出来了,基于字体混淆 & 加密技术,让当前 PDF 使用混淆 & 加密后的字体库。这样就算公开提供了 PDF 文件,客户复制后的文字也是混淆后的,也算保障了数据安全。
不过现在 OCR 这么强大,混淆字体后,仍然可以通过 OCR 的手段去识别,只是需要多花费一些精力而已。
电子签名 & 数字签名
电子签名 - Electronic Signature
美国 《全球和国家商业电子签名法》 (2000年)将“电子签名”定义为“附在合同上或通过电子方式生成,发送,传达,接收或存储的其他记录或与之逻辑关联的电子声音,符号或过程。”
实际上,电子签名只是将手写签名的图片,附在电子文档上,然后配合一些多因素身份验方式(PIN/密码/邮箱)证来完成。
数字签名 - Digital Signature
数字签名和电子签名不同,数字签名需要配合 PKI 认证中心(CA)颁发的数字证书实现,基本玩法是这样:
- 对内容使用摘要算法(如MD/SHA等)生成摘要
- 使用非对称加密算法+证书私钥对摘要进行加密
- 将加密的摘要数据,和签名的证书(公钥部分)附在PDF文件中
从上面的步骤可以看出,PDF 数字签名和 SSL 加密并不一样,PDF 本质上是对文件“签名”,可以保证文件签名者的身份,保证不可篡改,而 SSL 是对报文进行加密。
下图是非对称加密算法下,加密和数字签名的区别:
总结一下,非对称加密算法的主流应用就两种:公钥加密 -> 私钥解密,私钥加密 -> 公钥验签。
PDF 数字签名还有个特殊的玩法,可以将数字签名信息和图片进行“绑定”,比如电子发票里的签章(Stamp)图片,这个图片可以作为数字签名的外观(Appearance)。
如果不使用外观,只进行数字签名当然也是可以的。不过记住一点:有签章图片不一定有数字签名,有数字签名也不一定有签章图片,这俩不是一个东西。
其实不止是 PDF 文件才可以数字签名,微软家的 Office 套件也是支持数字签名的,但一般没人会对 Office 格式的文件签名,所以市面上能见到的都是对 PDF 数字签名。
签名验证
PDF 签名验证的原理也很简单:
验证PDF 的签名证书是否受信
- 使用客户端根证书库(比如Adobe PDF,会使用内置的根证书列表,和操作系统无关),验证签名证书是否受信
通过证书的公钥,对签名后的摘要数据进行验签。
证书 & 签名算法
PDF 数字签名所使用的证书类型,和 SSL 是不一样的。普通 SSL 的证书验证域名所有者就可以了,而 PDF 数字签名所使用的证书一般称为机构证书,没有域名的概念,但会严格的验证企业信息,如营业许可证等等。
目前主流的数字证书非对称加密算法有RSA/DSA/DSS,但应用最广的还是 RSA 算法,不过随着国产化的趋势,金融保险等行业慢慢的迁移到国密算法了。
不过算法不重要,都是非对称加密,都是数字证书,只是具体签名/验签/加密/解密的算法不同而已。
表单域 - Acro Form
表单域就是指 PDF 表单,英文定义叫 Acro Form。是的你没看错,PDF 也有和 HTML 类似的表单技术,表单里可以配置文本域、单选框、复选框等元素:
编辑好了 PDF 表单之后,就可以通过工具或程序,对PDF进行填充或者填写了。
PDF 库(JAVA)
PDF 技术还是比较封闭的,开源库用起来会非常不爽,如果企业商用的话,尽量还是考虑买商业 SDK,功能丰富,文档完善,花钱买时间。
开源 & 免费
- Itext - 4.x 版本以下免费,5以上的版本开源许可为AGPL,商用需要付费
- Openpdf - 基于 itext 2.x 版本修复,还是Itext
- pdfbox - Apache 下开源的 PDF 库,虽然免费,但功能远不如 Itext,不推荐使用。
还有一些更小众的PDF库,这里就不推荐了。目前使用最多的是 itext,pdfbox 虽然完全开源免费,但功能和文档丰富程度远不及 itext。
商业
- Itext 7 - 有 JAVA 和 C# 两个版本,功能全,文档完善,基本能满足你对PDF的所有要求。
- Aspose.PDF - 提供了多语言的 SDK,功能强大,文档也比较丰富
- Spire.PDF - 提供了多语言的 SDK,功能强大,文档也比较丰富,而且不只是PDF,还支持Office全家桶,在国内也有经销商
- Adobe PDF Library SDK - Adobe 自家的 PDF SDK,功能肯定是最全的,支持多语言
- Datalogics PDF Java Toolkit - Datalogics 是 Adobe PDF Library 的代理商,同时自己也提供了另一个版本的 PDF SDK
PDF 工具
PDF 工具市面上一大堆,下面列出一些主流的功能完善的 GUI 工具(阅读、编辑、转换、签名):
- Adobe Acrobat- PDF 的鼻祖,最强 PDF 工具,没有之一
- 福昕 - 国产老牌 PDF 软件
- 万兴PDF
- 迅捷办公
- small pdf - 良心的 PDF 在线工具网站,编辑、转换等功能都有,兼容性也很好,而且每天有一定免费配额
参考
- https://www.wikiwand.com/zh/%E5%8F%AF%E7%A7%BB%E6%A4%8D%E6%96%87%E6%A1%A3%E6%A0%BC%E5%BC%8F
- https://www.ssl.com/zh-CN/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D%E5%92%8C%E6%96%87%E4%BB%B6%E7%AD%BE%E5%90%8D/
- https://www.wosign.com/FAQ/faq_2019070401.htm
- http://gmssl.org/
- https://itextpdf.com/sites/default/files/2018-12/digitalsignatures20130304.pdf
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。