Java使用Itext5.5.10进行pdf签章

来源:Java使用Itext5.5.10进行pdf签章_liumengya007007的博客-CSDN博客_itext 签章

啰嗦

说到PDF数字签名签章,这个其实也是数字证书信息安全的应用范畴,关于数字证书和数字签名,网上有很多解释说明,但讲解都多不够详细准确,这边推荐一篇大神的博文,讲解浅显易懂形象数字证书 数字签名 数据加密。刚入门CA行业的人,可以入门看看。 
言归正传,正文开始

Itext包 和 BC包

要自己实现PDF数字签章,是一件极其浩大的工程,难度很大(看看市面上多少公司是吃这一行的饭就知道了),好在java是个开源的世界,有很多开源项目。这里,咱们使用itext来实现一下pdf的数字签章(为什么挑itext,很大原因是,自己在做这一块的时候,网上对于itext的使用也有很多博文,不过,大多都是用的比较早期的itext,itext官网目前的版本的已经有了变化,网上普遍的做法都已经不适用了,还有一个原因,itext官网有官方教程,各个模块的样例,很方便)。 
如果不知道在官网怎么下载jar包,这里附上我自己的下载地址方便大家, itextpdf-5.5.10 源码、jar包、doc文档 ,另外还需要密钥算法包bouncycastle.org ,这个官网下载很简单,官网地址如下bouncycastle.org官网。

开始

咱们跟随样例,先来一个简单的签章。步骤如下: 
一、准备一个pdf文档(貌似是废话) 
二、准备一个图章图片(貌似也是废话) 
三、准备一个keystore(只要是java keystore支持的格式都可以,例如.p12,如果没有,可以用bouncycastle生成一个,也很简单)。其实,Usbkey数字证书也是可以使用的,后边我再说这一块。 
四、按照官网样例,写个.p12的签章代码。

代码

1、新建Java项目,导入itext包和 bc包 
准备需要的资料 
导入的包,应该有多余的包,我直接从项目中复制出来的

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.JOptionPane;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.log.Logger;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfSignatureAppearance.RenderingMode;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.CrlClient;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;


准备的资料

    public static final String KEYSTORE = "F:\\ZzCert\\test.p12";public static final char[] PASSWORD = "111111".toCharArray();//keystory密码public static final String SRC = "F:\\test\\src.pdf";public static final String DEST = "F:\\test\\signed_dest.pdf";

2、写个类,声明一个方法用来进行pdf签章

public void sign(String src  //需要签章的pdf文件路径, String dest  // 签完章的pdf文件路径, Certificate[] chain //证书链, PrivateKey pk //签名私钥, String digestAlgorithm  //摘要算法名称,例如SHA-1, String provider  // 密钥算法提供者,可以为null, CryptoStandard subfilter //数字签名格式,itext有2种, String reason  //签名的原因,显示在pdf签名属性中,随便填, String location) //签名的地点,显示在pdf签名属性中,随便填throws GeneralSecurityException, IOException, DocumentException {//下边的步骤都是固定的,照着写就行了,没啥要解释的// Creating the reader and the stamper,开始pdfreaderPdfReader reader = new PdfReader(src);//目标文件输出流FileOutputStream os = new FileOutputStream(dest);//创建签章工具PdfStamper ,最后一个boolean参数 //false的话,pdf文件只允许被签名一次,多次签名,最后一次有效//true的话,pdf可以被追加签名,验签工具可以识别出每次签名之后文档是否被修改PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);// 获取数字签章属性对象,设定数字签章的属性PdfSignatureAppearance appearance = stamper.getSignatureAppearance();appearance.setReason(reason);appearance.setLocation(location);//设置签名的位置,页码,签名域名称,多次追加签名的时候,签名预名称不能一样//签名的位置,是图章相对于pdf页面的位置坐标,原点为pdf页面左下角//四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角yappearance.setVisibleSignature(new Rectangle(200, 200, 300, 300), 1, "sig1");//读取图章图片,这个image是itext包的imageImage image = Image.getInstance("F:\\test\\Dummy1.png"); appearance.setSignatureGraphic(image); appearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);//设置图章的显示方式,如下选择的是只显示图章(还有其他的模式,可以图章和签名描述一同显示)appearance.setRenderingMode(RenderingMode.GRAPHIC);// 这里的itext提供了2个用于签名的接口,可以自己实现,后边着重说这个实现// 摘要算法ExternalDigest digest = new BouncyCastleDigest();// 签名算法ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, null);// 调用itext签名方法完成pdf签章MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);}


3、main方法中调用签章 
调用代码很简单,如下

public static void main(String[] args)  {try {//读取keystore ,获得私钥和证书链KeyStore ks = KeyStore.getInstance("PKCS12");ks.load(new FileInputStream(KEYSTORE), PASSWORD);String alias = (String)ks.aliases().nextElement();PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);Certificate[] chain = ks.getCertificateChain(alias);//new一个上边自定义的方法对象,调用签名方法MainWindow app = new MainWindow();
//      app.sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA1, provider.getName(), CryptoStandard.CMS, "Test 1", "Ghent");
//      app.sign(SRC, String.format(DEST, 2), chain, pk, "SM3", provider.getName(), CryptoStandard.CADES, "Test 2", "Ghent");app.sign(SRC, String.format(DEST, 3), chain, pk, DigestAlgorithms.SHA1, null, CryptoStandard.CMS, "Test 3", "Ghent");
//      app.sign(SRC, String.format(DEST, 4), chain, pk, DigestAlgorithms.RIPEMD160, provider.getName(), CryptoStandard.CADES, "Test 4", "Ghent");} catch (Exception e) {// TODO Auto-generated catch blockJOptionPane.showMessageDialog(null, e.getMessage());e.printStackTrace();} }


4、运行main方法就可以了。效果如下,用adobe reader可以看到图章,可以获取签名信息

 

使用特殊签名算法

上边的例子中,使用的是比较常见的签名算法-sha1withRsa,itext支持国际流行的大部分签名算法。 
当然itext也支持特殊的签名算法,例如国密,为什么itext不把国密算法也封装进jar包呢,一个原因是国密并不是国际通用标准,二是即便把国密封装进jar包,进行完签名后,一般的pdf阅读器也是无法验签的,因为adobe 的pdf标准没有国密算法。 
即便如此,我们依然可以自己把国密算法加到itext签章中,只不过阅读器无法验签就对了。主要用的就是上边例子中的2个接口。

        // 摘要算法ExternalDigest digest ;// 签名算法ExternalSignature signature ;

我们可以通过自己实现这2个接口,来添加国密算法。 
看看这连个接口的源码,都很简单,digest接口返回MessageDigest,实现的时候,直接new 一个MessageDigest,然后实现MessageDigest的抽象方法,把自己实现的SM3算法加进去就可以了(SM3withSM2按照国密的标准,sm3要加预处理,具体怎么做,百度很多,这里不多说) 
signature 接口3个抽象方法,分别返回摘要算法名称(例如SM3 或者SHA1等),签名算法中使用的加密算法名称(例如SM2 或者RSA等), 第三个抽象方法sign就是具体的签名算法,传入的参数message是签名原文,返回值是签名结果,针对国密算法来说,就可以把自己实现好的 sm3withsm2签名算法 写进去。 
另外,需要注意,实现接口后,运行main会提示错误,原因是 自己实现的国密接口的OID并没有加入到itext源码中,可以根据错误提示,找到需要加入oid的地方,直接把算法oid写进去后 itext就可以认到我们自己实现的算法了。大致有2个地方要加,一个是摘要算法的oid,一个是签名算法的oid

package com.itextpdf.text.pdf.security;import java.security.GeneralSecurityException;
import java.security.MessageDigest;/**** @author psoares*/
public interface ExternalDigest {public MessageDigest getMessageDigest(String hashAlgorithm) throws GeneralSecurityException;
}
package com.itextpdf.text.pdf.security;import java.security.GeneralSecurityException;/*** Interface that needs to be implemented to do the actual signing.* For instance: you'll have to implement this interface if you want* to sign a PDF using a smart card.* @author Paulo Soares*/
public interface ExternalSignature {/*** Returns the hash algorithm.* @return  the hash algorithm (e.g. "SHA-1", "SHA-256,...")*/public String getHashAlgorithm();/*** Returns the encryption algorithm used for signing.* @return the encryption algorithm ("RSA" or "DSA")*/public String getEncryptionAlgorithm();/*** Signs it using the encryption algorithm in combination with* the digest algorithm.* @param message   the message you want to be hashed and signed* @return  a signed message digest* @throws GeneralSecurityException*/public byte[] sign(byte[] message) throws GeneralSecurityException;
}


UsbKey 数字证书签章

大家一定有 用UsbKey签章的需求,因为 软证书是不安全的,私钥容易被窃取,UsbKey数字证书才是最正规最安全的方案,上边说的都是基于软证书的,那么Ukey硬证书要怎么签章呢? 
同样的,我们还是利用如下这2个接口。不过,这次不用实现digest了,因为itext自己包含的digest算法都是可以满足的,直接用例子中的代码就可以。 
你说我的ukey 证书也是国密SM3withSM2的,那怎么办,我的回答是,国密算法的ukey最好不要用,因为还是那句话,即便实现了接口,签出来pdf后, 市面上主流pdf阅读器都不能验签,那就失去了签章的意义。除非,自己写一个阅读器。。。 
(可以点开源码看看itext oid中都包含那些算法,目前咱们用得到的算法,除了国密算法,其他的算法基本都可以支持)

        // 摘要算法ExternalDigest digest = new BouncyCastleDigest();;// 签名算法ExternalSignature signature ;

OK,Ukey怎么调用,很简单,同样是 实现signature接口,把你的ukey的摘要算法和加密算法名称返回, sign函数中, 调用你的Ukey的签名算法就行了。 
比如,你的Ukey是windows平台的,Ukey厂家肯定给你有Ukey驱动和 算法dll,我们需要做的就是,用java写个jni接口,添加native方法,然后javah生成.h头文件,然后在用c或者c++调用厂家的dll实现jni接口, 然后在 ExternalSignature的sign方法中调用native方法就可以了。 
当然,自己封装的 签名函数传入的参数就要变一变了,例如私钥 就直接传入null

import java.io.File;public class NativeMethods {static {String parentPath="D:\\dll\\";String dllName="NativeCode.dll";File dll=new File(parentPath+dllName);if (dll.exists()) {
//      System.loadLibrary(dllName);//dll必须方法系统环境变量下System.load(parentPath+dllName); //可以指定任意位置}}//进行签名,传入签名原文,返回签名结果public native String signByUKEY(String message);//获取签名公钥证书public native String getSignCer();
}


使用远程服务器签名的方式签章

看了上边内容,估计你也会举一反三的 实现 服务器形式的 签名了,没错,就是实现 签名接口ExternalSignature signature ;,在sign方法中访问 服务器签名接口 传送签名原文,返回签名结果就可以了。

结语

OK了,itext 进行pdf签章这块就说完了,希望对大家有所帮助。 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/496235.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python的bool类型

写习惯了C#的代码,在想要将一个字符串False转换为bool型的时候,很自然的写了如下的Python代码: 看到上面的结果了没?是True。突然记起Python中除了、""、0、()、[]、{}、None为False之外,其他的都是True。也…

工业机器人发展趋势分析 未来营收规模达到百亿级水平

来源:前瞻产业研究院摘要:工业机器人是打造自动化工厂的重要组成,可有效提高效率生产、降低成本和控制质量。工业机器人是面向工业领域的多关节机械手或多自由度的机器装置,它能自动执行工作,是靠自身动力和控制能力来实现各种功能的一种机器。工业机器人…

【itext学习之路】--5.对pdf进行盖章/签章/数字签名

来源:【itext学习之路】-------(第五篇)对pdf进行盖章/签章/数字签名_tomatocc的博客-CSDN博客_itext 数字签名 在上一篇文章中,我们学习了使用itext对pdf增加图片水印和文本水印,那么这篇文章我们将要学习更高级一点…

python selenium 用法 和 Chrome headless

From: http://cuiqingcai.com/2599.html Selenium教程:https://www.yiibai.com/selenium selenium 官方参考文档:https://selenium-python.readthedocs.io/index.html Selenium Documentation:https://www.seleniumhq.org/docs Selenium 与 …

【itext学习之路】--1.创建一个简单的pdf文档

来源:https://blog.csdn.net/tomatocc/article/details/80666011 iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件 本教程中…

并发服务器设计思路,参考apache学习UDP和QoS,研究成果

研究了快1个月的服务器架构,把研究成果记录一下。参考的有:Apache vlc ACE ftp我主要需要其中的并发处理,内存管理,TCP/UDP.QoS,速度限制等方面的内容,所以着重说这几方面。首先看一下Apache的基本框图&…

一文看懂NB-IoT!

来源:物联江湖(iot521) 作者:王一鸣一直以来,人们通过相应的终端(电脑、手机、平板等)使用网络服务,“个人”一直是网络的用户主体。个人对网络质量的要求“高”且“统一”:玩网络游戏必需要低…

安装、配置 Java JDK 和 JRE,并卸载自带 OpenJDK

JRE 和 JDK 的区别是什么?:https://www.zhihu.com/question/20317448 如何配置 Java 环境变量:https://jingyan.baidu.com/article/fd8044fa2c22f15031137a2a.html Windows 10 配置Java 环境变量:https://www.runoob.com/w3cnote…

将十进制数转为N进制的方法

设有一个数 A,比如 A15 ,转为四进制数应当表示为33.原理如下:1.A除N,2.A模N.3.保存A模N的值。4.循环1&#xff0c;2。直到 A除N的值等于0;Codeclass NumerationConverter { /// <summary> /// 将十进制度数转为四进制 /// </summary> …

人工智能即将冲击与改变现有的医疗方式

来源呢&#xff1a;千家网从1960年代初&#xff0c;学术界陆续展开对于人工智能的研究&#xff0c;一直到目前的机器学习、深度学习等观念&#xff0c;所带来的第三波人工智能浪潮。对于医疗领域来说&#xff0c;在1970年代初期&#xff0c;人工智能就已经被应用在各项检查&…

【itext学习之路】--2.设置pdf的一些常用属性

来源&#xff1a;https://blog.csdn.net/tomatocc/article/details/80666361 在上一篇文章中&#xff0c;我们已经成功的创建了一个简单的pdf&#xff0c;下面我将学习设置该pdf的常用属性&#xff0c;其中包括&#xff1a;作者&#xff0c;创建时间&#xff0c;pdf创建者&…

简单好用的 Linux/Windows 面板

简单好用的 Linux/Windows 面板宝塔官网&#xff1a;https://www.bt.cn 宝塔Linux面板新手安装教程&#xff1a;https://www.cnblogs.com/paul8339/p/7065799.html https://blog.csdn.net/letterss/article/details/80216091 宝塔面板手册截图&#xff08;地址&#xff1a;http…

任正非:中美领跑AI说法不合适、5G被炒作过热……

来源&#xff1a;羊城晚报 作者&#xff1a;宋毅摘要&#xff1a;2017年&#xff0c;华为又交出漂亮答卷&#xff1a;实现全球销售收入6036亿元&#xff0c;同比增长15.7%。4日&#xff0c;任正非接受了羊城晚报等5家媒体的采访&#xff0c;谈到了华为每年15%的研发投入&#…

【itext学习之路】--3.对pdf文档进行加密和权限设置

来源&#xff1a;https://blog.csdn.net/tomatocc/article/details/80667838 上篇文章&#xff0c;我们学习了pdf的属性设置&#xff0c;但是我们知道&#xff0c;在实际开发中&#xff0c;如果pdf文档被黑客盗取的话&#xff0c;那么pdf中的信息就会被泄露&#xff0c;因此本…

scrapy 模拟登陆

python 模拟登录豆瓣 并 发表动态&#xff1a;https://blog.csdn.net/freeking101/article/details/65445551 python网络爬虫之使用scrapy自动登录网站&#xff1a;https://www.cnblogs.com/zhanghongfeng/p/7684415.html Scrapy笔记&#xff08;11&#xff09;- 模拟登录&am…

李国杰院士等:未来移动通信系统中的通信与计算融合

来源 5G 作者&#xff1a;周一青 李国杰周一青&#xff1a;中国科学院大学教授&#xff0c;中国科学院计算技术研究所“百人计划”研究员、博导&#xff0c;无线通信技术研究中心副主任&#xff0c;移动计算与新型终端北京市重点实验室研究员。李国杰&#xff1a;中国工程院院…

【itext学习之路】--4.给pdf增加文本水印和图片水印

来源&#xff1a;【itext学习之路】-------&#xff08;第四篇&#xff09;给pdf增加文本水印和图片水印_tomatocc的博客-CSDN博客_itext添加水印 一般而言&#xff0c;许多公司在做pdf之后&#xff0c;都会将公司的logo或者网址以水印的方式添加到pdf文件中。本篇文章&#x…

Postman 使用方法详解

From&#xff1a;https://blog.csdn.net/fxbin123/article/details/80428216 Postman使用详解&#xff1a;https://www.cnblogs.com/xiaoxi-3-/p/7839278.html Postman用法简介&#xff1a;https://blog.csdn.net/flowerspring/article/details/52774399 Postman 详解&#xff…

基于互联网大脑架构的腾讯未来趋势分析[系列1]

作者&#xff1a;刘锋&#xff0c;计算机博士 《互联网进化论》前言互联网大脑架构不是人为规划出来的&#xff0c;而是过去50年&#xff0c;互联网在科学探索和商业竞争两大动力推动下&#xff0c;形成的类脑架构。它的提出是基于2008年以来&#xff0c;我们对移动互联网&…

Linux看内存标压低压,三代锐龙、国产Linux上身笔记本电脑,性能是否和参数一样好看?...

原标题&#xff1a;三代锐龙、国产Linux上身笔记本电脑&#xff0c;性能是否和参数一样好看&#xff1f;如果你从很早开始就关注电脑行业&#xff0c;基本上你身边的朋友都会告诫你一句&#xff1a;“笔记本电脑千万别买AMD的……”并不是AMD不好&#xff0c;说实话&#xff0c…