生活随笔
收集整理的這篇文章主要介紹了
【itext学习之路】--5.对pdf进行盖章/签章/数字签名
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
來源:【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-1private String imagePath;//圖章路徑private String fieldName;//表單域名稱private Certificate[] chain;//證書鏈private PrivateKey pk;//簽名私鑰private int certificationLevel = 0; //批準簽章private PdfSignatureAppearance.RenderingMode renderingMode;//表現形式:僅描述,僅圖片,圖片和描述,簽章者和描述//圖章屬性private float rectllx ;//圖章左下角xprivate float rectlly ;//圖章左下角yprivate float recturx ;//圖章右上角xprivate float rectury ;//圖章右上角ypublic 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,圖章右上角yappearance.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,CADEMakeSignature.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);//需要進行簽章的pdfString 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+中文使用說明》?
總結
以上是生活随笔為你收集整理的【itext学习之路】--5.对pdf进行盖章/签章/数字签名的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。