【itext学习之路】

您所在的位置:网站首页 签章是签名加盖章吗 【itext学习之路】

【itext学习之路】

2024-01-04 16:15| 来源: 网络整理| 查看: 265

来源:【itext学习之路】-------(第五篇)对pdf进行盖章/签章/数字签名_tomatocc的博客-CSDN博客_itext 数字签名

在上一篇文章中,我们学习了使用itext对pdf增加图片水印和文本水印,那么这篇文章我们将要学习更高级一点的水印----印章。可能你会有疑问,印章不也是一个图片吗?当然,你可以把一个印章图片来做成图片水印,但是我们这里要介绍的是,通过数字签名的方式来进行pdf签章。

首选,我们要准备好jar包。

bcpkix-jdk15on-1.49.jar bcprov-jdk15on-1.49.jar itext-asian-5.2.0.jar itextpdf-5.5.11-sources.jar itextpdf-5.5.11.jar

大家可以去maven库中进行下载,也可以直接下载我上传的jar包文件:点击下载

下载好jar包之后,我们还要去了解一门技术:数字证书,而在本文中,我们需要生成一个.p12结尾的数字证书,该证书用来对我们的pdf文档进行数字签名。生成.p12证书的方法请参考我的另一篇文章:使用JDK的keytool生成p12证书

直到这里,我们前期的准备工作就已经全部做好,接下来,我们就要步入正题:对pdf进行签章。 首先,我们创建一个SignatureInfo的实体类,用途是为了方便的增加需要签章的信息: package cn.tomtocc.pdf; import com.itextpdf.text.pdf.PdfSignatureAppearance; import java.security.PrivateKey; import java.security.cert.Certificate; public class SignatureInfo { private String reason; //签名的原因,显示在pdf签名属性中 private String location;//签名的地点,显示在pdf签名属性中 private String digestAlgorithm;//摘要算法名称,例如SHA-1 private String imagePath;//图章路径 private String fieldName;//表单域名称 private Certificate[] chain;//证书链 private PrivateKey pk;//签名私钥 private int certificationLevel = 0; //批准签章 private PdfSignatureAppearance.RenderingMode renderingMode;//表现形式:仅描述,仅图片,图片和描述,签章者和描述 //图章属性 private float rectllx ;//图章左下角x private float rectlly ;//图章左下角y private float recturx ;//图章右上角x private float rectury ;//图章右上角y public float getRectllx() { return rectllx; } public void setRectllx(float rectllx) { this.rectllx = rectllx; } public float getRectlly() { return rectlly; } public void setRectlly(float rectlly) { this.rectlly = rectlly; } public float getRecturx() { return recturx; } public void setRecturx(float recturx) { this.recturx = recturx; } public float getRectury() { return rectury; } public void setRectury(float rectury) { this.rectury = rectury; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public String getDigestAlgorithm() { return digestAlgorithm; } public void setDigestAlgorithm(String digestAlgorithm) { this.digestAlgorithm = digestAlgorithm; } public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } public String getFieldName() { return fieldName; } public void setFieldName(String fieldName) { this.fieldName = fieldName; } public Certificate[] getChain() { return chain; } public void setChain(Certificate[] chain) { this.chain = chain; } public PrivateKey getPk() { return pk; } public void setPk(PrivateKey pk) { this.pk = pk; } public int getCertificationLevel() { return certificationLevel; } public void setCertificationLevel(int certificationLevel) { this.certificationLevel = certificationLevel; } public PdfSignatureAppearance.RenderingMode getRenderingMode() { return renderingMode; } public void setRenderingMode(PdfSignatureAppearance.RenderingMode renderingMode) { this.renderingMode = renderingMode; } } 第二步,我们创建一个用于对pdf签章的工具类,以及main方法 package cn.tomtocc.pdf; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Image; import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfSignatureAppearance; import com.itextpdf.text.pdf.PdfStamper; import com.itextpdf.text.pdf.security.BouncyCastleDigest; 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.PrivateKeySignature; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; public class ItextUtil { public static final char[] PASSWORD = "123456".toCharArray();// keystory密码 /** * 单多次签章通用 * * @param src * @param target * @param signatureInfos * @throws GeneralSecurityException * @throws IOException * @throws DocumentException */ @SuppressWarnings("resource") public void sign(String src, String target, SignatureInfo signatureInfo) { InputStream inputStream = null; FileOutputStream outputStream = null; ByteArrayOutputStream result = new ByteArrayOutputStream(); try { inputStream = new FileInputStream(src); ByteArrayOutputStream tempArrayOutputStream = new ByteArrayOutputStream(); PdfReader reader = new PdfReader(inputStream); // 创建签章工具PdfStamper ,最后一个boolean参数是否允许被追加签名 // false的话,pdf文件只允许被签名一次,多次签名,最后一次有效 // true的话,pdf可以被追加签名,验签工具可以识别出每次签名之后文档是否被修改 PdfStamper stamper = PdfStamper.createSignature(reader, tempArrayOutputStream, '\0', null, true); // 获取数字签章属性对象 PdfSignatureAppearance appearance = stamper .getSignatureAppearance(); appearance.setReason(signatureInfo.getReason()); appearance.setLocation(signatureInfo.getLocation()); // 设置签名的位置,页码,签名域名称,多次追加签名的时候,签名预名称不能一样 图片大小受表单域大小影响(过小导致压缩) // 签名的位置,是图章相对于pdf页面的位置坐标,原点为pdf页面左下角 // 四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角y appearance.setVisibleSignature( new Rectangle(signatureInfo.getRectllx(), signatureInfo .getRectlly(), signatureInfo.getRecturx(), signatureInfo.getRectury()), 1, signatureInfo .getFieldName()); // 读取图章图片 Image image = Image.getInstance(signatureInfo.getImagePath()); appearance.setSignatureGraphic(image); appearance.setCertificationLevel(signatureInfo .getCertificationLevel()); // 设置图章的显示方式,如下选择的是只显示图章(还有其他的模式,可以图章和签名描述一同显示) appearance.setRenderingMode(signatureInfo.getRenderingMode()); // 摘要算法 ExternalDigest digest = new BouncyCastleDigest(); // 签名算法 ExternalSignature signature = new PrivateKeySignature( signatureInfo.getPk(), signatureInfo.getDigestAlgorithm(), null); // 调用itext签名方法完成pdf签章 //数字签名格式,CMS,CADE MakeSignature.signDetached(appearance, digest, signature, signatureInfo.getChain(), null, null, null, 0, MakeSignature.CryptoStandard.CADES); inputStream = new ByteArrayInputStream( tempArrayOutputStream.toByteArray()); // 定义输入流为生成的输出流内容,以完成多次签章的过程 result = tempArrayOutputStream; outputStream = new FileOutputStream(new File(target)); outputStream.write(result.toByteArray()); outputStream.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != outputStream) { outputStream.close(); } if (null != inputStream) { inputStream.close(); } if (null != result) { result.close(); } } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { try { ItextUtil app = new ItextUtil(); // 将证书文件放入指定路径,并读取keystore ,获得私钥和证书链 String pkPath = "D:/server.p12"; KeyStore ks = KeyStore.getInstance("PKCS12"); ks.load(new FileInputStream(pkPath), PASSWORD); String alias = ks.aliases().nextElement(); PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD); // 得到证书链 Certificate[] chain = ks.getCertificateChain(alias); //需要进行签章的pdf String path = "D:/demo.pdf"; // 封装签章信息 SignatureInfo signInfo = new SignatureInfo(); signInfo.setReason("理由"); signInfo.setLocation("位置"); signInfo.setPk(pk); signInfo.setChain(chain); signInfo.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED); signInfo.setDigestAlgorithm(DigestAlgorithms.SHA1); signInfo.setFieldName("demo"); // 签章图片 signInfo.setImagePath("d:/sign.jpg"); signInfo.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC); signInfo.setRectllx(100); // 值越大,代表向x轴坐标平移 缩小 (反之,值越小,印章会放大) signInfo.setRectlly(200); // 值越大,代表向y轴坐标向上平移(大小不变) signInfo.setRecturx(400); // 值越大 代表向x轴坐标向右平移 (大小不变) signInfo.setRectury(100); // 值越大,代表向y轴坐标向上平移(大小不变) //签章后的pdf路径 app.sign(path, "D:/demo3.pdf", signInfo); } catch (Exception e) { e.printStackTrace(); } } }

为了方便各位理解,这里我将d盘所用到的文件在这里截图展示。

 

然后我们打开demo3.pdf,就可以看到pdf中已经有一个印章了,如果各位对上面代码中的一些参数不是很了解,欢迎留言交流。

在这里插入图片描述

点击下载《ITEXT官方英文API+中文使用说明》 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3