一、 概述
印章是我国特有的历史文化产物,古代主要用作身份凭证和行驶职权的工具。它的起源是由于社会生活的实际需要。早在商周时代,印章就已经产生。如今的印章已成为一种独特的,融实用性和艺术性为一体的艺术瑰宝。传统的印章容易被坏人、小人私刻;从而新闻鲜有报道某某私刻公章,侵吞国家财产。随着计算机技术、加密技术及图像处理技术的发展,出现了电子签章。电子签章是电子签名的一种表现形式,利用图像处理技术、数字加密技术将电子签名操作转化为与纸质文件盖章操作相同的可视效果,同时利用电子签名技术保障电子信息的真实性和完整性以及签名人的不可否认性。
电子签章与数字证书一样是身份验证的一种手段,泛指所有以电子形式存在,依附在电子文件并与其逻辑关联,可用以辨识电子文件签署者身份,保证文件的完整性,并表示签署者同意电子文件所陈述事实的内容。一般来说对电子签章的认定都是从技术角度而言的。主要是指通过特定的技术方案来鉴别当事人的身份及确保电子资料内容不被篡改的安全保障措施。电子签章常于发送安全电子邮件、访问安全站点、网上招标投标、网上签约、安全网上公文传送、公司合同、电子处方笺等。
电子签章是一个很复杂的问题,大到有相关的电子签章系统;今天分享一下如何把电子签章应用到电子处方笺的PDF文件里。
二、 技术选型
目前主流处理PDF文件两个jar包分别是:
开源组织Apache的PDFBox,官网https://pdfbox.apache.org/
大名鼎鼎adobe公司的iText,官网https://itextpdf.com/tags/adobe,其中iText又分为iText5和iText7
如何在PDFBox、iText5和iText7选出合适自己项目的技术呢?
对比PDFBox、iText5和iText7这三者:
PDFBox的功能相对较弱,iText5和iText7的功能非常强悍;
iText5的资料网上相对较多,如果出现问题容易找到解决方案;PDFBox和iText7的网上资料相对较少,如果出现问题不易找到相关解决方案;
通过阅读PDFBox代码目前PDFBox还没提供自定义签章的相关接口;iText5和iText7提供了处理自定义签章的相关实现;
PDFBox只能实现把签章图片加签到PDF文件;iText5和iText7除了可以把签章图片加签到PDF文件,还可以实现直接对签章进行绘制,把文件绘制到签章上。
PDFBox和iText5/iText7使用的协议不一样。PDFBox使用的是APACHE LICENSE VERSION 2.0(https://www.apache.org/licenses/);iText5/iText7使用的是AGPL(https://itextpdf.com/agpl)。PDFBox免费使用,AGPL商用收费
本分享JAVA对PDF文件进行电子签章需要实现的功能:
生成证书。与PDFBox、iText5和iText7技术无关
按模板输出PDF文件:PDFBox、iText5和iText7都可以完成,但是PDFBox会遇到中文乱码比较棘手的问题
在PDF文件中实现把签章图片加签到PDF文件:PDFBox、iText5和iText7都可以实现,没有很多的区别
在PDF文件中绘制签章:iText5和iText7都可以实现,PDFBox目前不支持
在PDF文件中生成高清签章:iText5和iText7都可以实现,PDFBox目前不支持
在PDF文件中进行多次签名::PDFBox、iText5和iText7都可以完成,没有区别
通过相关技术分析和要实现的功能分析,采用iText5进行开发,唯一遗憾的是iText商用收费;但是这不是做技术需要关心的!!选用iText5的理由:
使用iText5能实现全部的功能
如何在开发中遇到相关问题,容易找到相应解决方案
三、 生成一个图片签章
1. 生成一个如下图的签章图片
2. 相关代码
四、 如何按模板生成PDF文件
1. 制作PDF模板
目前PDF模板工具别无他物,只能使用伟大的Adobe公司提供的Adobe Acrobatpro DC软件进行制作。如何使用该软件这里就不多说了,如果在使用中遇到什么可以另外咨询。
2. 制作一个如下图的PDF模板,该模板是带有PDF的表单域的
五、 如何生成PKCS12证书
1. PKCS的简单介绍
PKCS:The Public-Key Cryptography Standards (简称PKCS)是由美国RSA数据安全公司及其合作伙伴制定的一组公钥密码学标准,其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。
到1999年底,PKCS已经公布了以下标准:
PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封[22]。
PKCS#3:定义Diffie-Hellman密钥交换协议[23]。
PKCS#5:描述一种利用从口令派生出来的安全密钥加密字符串的方法。使用MD2或MD5 从口令中派生密钥,并采用DES-CBC模式加密。主要用于加密从一个计算机传送到另一个计算机的私人密钥,不能用于加密消息[24]。
PKCS#6:描述了公钥证书的标准语法,主要描述X.509证书的扩展格式[25]。
PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息[26]。
PKCS#8:描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等[27]。
PKCS#9:定义一些用于PKCS#6证书扩展、PKCS#7数字签名和PKCS#8私钥加密信息的属性类型[28]。
PKCS#10:描述证书请求语法[29]。
PKCS#11:称为Cyptoki,定义了一套独立于技术的程序设计接口,用于智能卡和PCMCIA卡之类的加密设备[30]。
PKCS#12:描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法[31]。
PKCS#13:椭圆曲线密码体制标准[32]。
PKCS#14:伪随机数生成标准。
PKCS#15:密码令牌信息格式标准[33]。
PKCS12也就是以上标准的PKCS#12,主要用来描述个人身份信息;本次分享中要进行签章操作的是医生和药师,他们就是一个个人主体,给他们分配一个PKCS12的证书,就等于给他们分配了一个用于盖章的印章。
2. 使用JAVA生成一个PKCS12证书并进行存贮,相关分析见代码注解
六、 如何生成一个高清晰的签章
1. 由PDF模板生成一个PDF文件,见代码注解
2. 对PDF文件进行签章
经过过上面的代码可以生成一个名为sign.jpg的签章图片,生成一个keystore.p12的证书文件,还有一个已经通过模板填充了表单的名为filled.pdf的pdf文件。下面就可通过以上材料生成一个签名的PDF文件。
3. 高清签章
高清签章是通过iText的绘制功能来完成。主要直接在PDF文件中绘制签章,代码实现如下:
可以分析下下面这两个签章的区别,发现左边的签章很模糊,右边的特别清晰。
七、 如何进行多次PDF签名
生成多个签章重点代码,已在SignPdf.java类进行标注说明;如果想进行多次签名,就只需对已经进行过签名的PDF文件再次调用sign方法进行再次签名即可(第六点有张图片就有两个签章,这就是多次签名的结果)。
PdfStamper.createSignature(reader, signPDFData, '\0', temp, true);
八、 总结
分享中sign.jpg文件的白色背景需要做透明化处理才能达到正确电子签章的效果(不覆盖PDF文件中已有的内容,真实的电子签章也是这样做的),大家回去可以思考下怎么把一个jpg文件白色背景透明化(高清签章就已经实现透明化,可以试着把SignPdf.java和SignHighPdf.java签章到有文字的PDF上面看看效果)。
大家见到的公司公章都是圆形的;这个也是可以做到的大家想想怎样生成一个圆形的图片签章;然后进行电子签名。这里主要是讲解代码实现,所有代码非常多。大家回去好好研读代码。真正的电子签名需要通过CA认证公司来完成,我这里只是提供参考方案让大家学习。