java对现有的pdf添加签名、签章
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
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 com.wanbo.vo.BalanceBaseInfo;
/**
* 对现有的对账单pdf签名并按规则命名存放
*
* EditPdfStatementSeal.java Create on 2020-06-02 下午2:09:22
*
*/
public class EditPdfStatementSeal implements Runnable{
//对账单源地址
private String statementFilePath;
//对账单目的地址
private String destStatementFilePath;
//印章图片地址
private String assetSeal;
//签名证书地址
private String signPath;
//填充信息
private BalanceBaseInfo balanceBaseInfo;
@Override
public void run(){
sealPdf();
}
public void sealPdf(){
try {
//原pdf输入流
FileInputStream sourceInputStream = new FileInputStream(statementFilePath);
//目标pdf输出流
FileOutputStream destOutputStream = new FileOutputStream(destStatementFilePath);
//签名证书
FileInputStream signInputStream = new FileInputStream(signPath);
//签名密钥
char[] password = "elink@D18".toCharArray();
//读取keystore ,获得私钥和证书链
KeyStore keyStore = KeyStore.getInstance("jks");
//载入密码和证书流
keyStore.load(signInputStream, password);
//获取私钥
String alias = (String)keyStore.aliases().nextElement();
PrivateKey pk = (PrivateKey) keyStore.getKey(alias, password);
//获取证书链
Certificate[] chain = keyStore.getCertificateChain(alias);
//读取原pdf文件
PdfReader reader = new PdfReader(sourceInputStream);
//目标文件输出流
//创建签章工具PdfStamper ,最后一个boolean参数
//false的话,pdf文件只允许被签名一次,多次签名,最后一次有效
//true的话,pdf可以被追加签名,验签工具可以识别出每次签名之后文档是否被修改
PdfStamper stamper = PdfStamper.createSignature(reader, destOutputStream, '\0', null, false);
//给pdf追加内容:企业名称,对账人姓名,对账日期
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
Font font = new Font(baseFont);
font.setColor(BaseColor.RED);
PdfContentByte over = stamper.getOverContent(1);
ColumnText columnText = new ColumnText(over);
columnText.setSimpleColumn(150, 44, 1200, 20);
Paragraph elements = new Paragraph(0, new Chunk(balanceBaseInfo.getParam1()+"|"+balanceBaseInfo.getParam2()+"|"+balanceBaseInfo.getParam3()));
elements.setFont(font);
columnText.addElement(elements);
columnText.go();
// 获取数字签章属性对象,设定数字签章的属性
PdfSignatureAppearance pdfAppearance = stamper.getSignatureAppearance();
pdfAppearance.setReason("对账行为签章");
pdfAppearance.setLocation(balanceBaseInfo.getParam1()+"|"+balanceBaseInfo.getParam2()+"|"+balanceBaseInfo.getParam3());
//设置签名的位置,页码,签名域名称,多次追加签名的时候,签名预名称不能一样
int pageCount = reader.getNumberOfPages();
//签名的位置,是图章相对于pdf页面的位置坐标,原点为pdf页面左下角
//四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角y
pdfAppearance.setVisibleSignature(new Rectangle(40, 0, 143, 93), pageCount, "param13");
//读取图章图片,这个image是itext包的image
Image image = Image.getInstance(assetSeal);
pdfAppearance.setSignatureGraphic(image);
pdfAppearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED);
//设置图章的显示方式,如下选择的是只显示图章(还有其他的模式,可以图章和签名描述一同显示)
pdfAppearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
// 这里的itext提供了2个用于签名的接口,可以自己实现,后边着重说这个实现
// 摘要算法
ExternalDigest digest = new BouncyCastleDigest();
// 签名算法
ExternalSignature signature = new PrivateKeySignature(pk, DigestAlgorithms.SHA1, null);
// 调用itext签名方法完成pdf签章CryptoStandard.CMS 签名方式,建议采用这种
MakeSignature.signDetached(pdfAppearance, digest, signature, chain, null, null, null, 0, MakeSignature.CryptoStandard.CMS);
stamper.close();
reader.close();
sourceInputStream.close();
destOutputStream.close();
signInputStream.close();
} catch (Exception e) {
LogUtils.errorOutPutInfo("----pdf sign is error");
}
}
public String getStatementFilePath() {
return statementFilePath;
}
public void setStatementFilePath(String statementFilePath) {
this.statementFilePath = statementFilePath;
}
public String getAssetSeal() {
return assetSeal;
}
public void setAssetSeal(String assetSeal) {
this.assetSeal = assetSeal;
}
public BalanceBaseInfo getBalanceBaseInfo() {
return balanceBaseInfo;
}
public void setBalanceBaseInfo(BalanceBaseInfo balanceBaseInfo) {
this.balanceBaseInfo = balanceBaseInfo;
}
public String getDestStatementFilePath() {
return destStatementFilePath;
}
public void setDestStatementFilePath(String destStatementFilePath) {
this.destStatementFilePath = destStatementFilePath;
}
public String getSignPath() {
return signPath;
}
public void setSignPath(String signPath) {
this.signPath = signPath;
}
}
版权声明:本文为weixin_44865161原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。