public class ReadMe {
public static void main(String[] args) throws Exception {
//1、創建PDF閱讀器
PdfReader pdfReader = new PdfReader("需要簽章的PDF文件路徑");
//2、創建簽章工具PdfStamper
//最後一個參數false的話:PDF文件只允許被簽名一次,多次簽名時最後一次有效;true的話:可以被追加簽名,驗籤工具可以識別出每次簽名之後文檔是否被修改
PdfStamper pdfStamper = PdfStamper.createSignature(pdfReader, new FileOutputStream("簽章後的PDF文件路徑"),
'\0', null, true);
//3、創建數字簽名域
int x = 300, y = 400, width = 200, height = 200;
Rectangle areaSignatureRect = new Rectangle(x, y, x + width, y + height); //簽名區域
PdfFormField formField = PdfFormField.createSignature(pdfStamper.getWriter());
formField.setFieldName("AREA_SIGNATURE"); //簽名域標識
formField.setPage(1); //PDF頁碼從1開始
formField.setWidget(areaSignatureRect, PdfAnnotation.HIGHLIGHT_OUTLINE); //高亮顯示
//可以通過PdfAppearance對象對這塊區域外觀做下調整
PdfAppearance pdfAppearance = PdfAppearance.createAppearance(pdfStamper.getWriter(), width, height); //設置區域的寬高和邊框厚度
pdfAppearance.setColorStroke(BaseColor.LIGHT_GRAY); //邊框顏色
pdfAppearance.setColorFill(BaseColor.YELLOW); //填充顏色
//填充矩形區域-開始
pdfAppearance.rectangle(0, 0, width, height);
//填充矩形區域-結束
pdfAppearance.fillStroke();
//添加文字
pdfAppearance.setColorFill(BaseColor.BLACK); //填充顏色重置爲黑色,用於顯示文字
ColumnText.showTextAligned(pdfAppearance, Element.ALIGN_CENTER, new Phrase("簽名區域",
new Font(Font.FontFamily.SYMBOL, 9.0F, Font.NORMAL, new BaseColor(0.0F, 0.0F, 0.0F, 0.5F))),
width / 2, height / 2, 0);
//將外觀應用到簽名域對象上
formField.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pdfAppearance);
//最後將簽名對象作爲標註添加到PdfStamper對象
pdfStamper.addAnnotation(formField, 1);
//3、獲取數字簽章屬性對象,設定數字簽章屬性(對簽名域的屬性進行調整)
PdfSignatureAppearance appearance = pdfStamper.getSignatureAppearance();
appearance.setReason("簽名原因,顯示在PDF簽名屬性中");
appearance.setLocation("簽名地點,顯示在PDF簽名屬性中");
//設置簽名的位置,頁碼、簽名域名稱,多次追加簽名的時候簽名域名稱不能一樣
appearance.setVisibleSignature(new Rectangle(200, 200, 300, 300), 1, "sig1");
//讀取印章圖片
Image image = Image.getInstance("C:\\gongzhang.png");
appearance.setSignatureGraphic(image);
appearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
//設置圖章的顯示方式,如下選擇的只是顯示圖章(還有其他模式,可以圖章和簽名描述一起顯示)
appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
//這裏iText提供了兩個用於簽名的接口,可以自己實現
ExternalDigest digest = new BouncyCastleDigest(); //摘要算法
//讀取keystore,獲取私鑰和證書鏈
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new FileInputStream("C:\\pdf\\test.p12"), "111111".toCharArray());
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, "111111".toCharArray()); //簽名私鑰
ExternalSignature signature = new PrivateKeySignature(pk, DigestAlgorithms.SHA1, null); //簽名算法
Certificate[] chain = ks.getCertificateChain(alias); //證書鏈
MakeSignature.CryptoStandard subFilter = MakeSignature.CryptoStandard.CMS; //數字簽名格式,iText有兩種
//調用iText簽名方法完成PDF簽章
MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null,
0, subFilter);
}
}