Itext对pdf模板进⾏电⼦签名最近在研究Itext对pdf进⾏签章,记录⼀下。
⼀。准备相关⽂件:
1.背景⾊为空的印章图⽚吉他d和弦
2.扩展名为.p12的证书(可⾃⾏百度keytool ⽣成证书 pkcs12)
3.⼀个使⽤acrobat处理过的pdf模板(使⽤数字签名表单)
⼆。引⼊相关maven依赖:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.49</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
苏菲是谁<artifactId>bcpkix-jdk15on</artifactId>
<version>1.49</version>
</dependency>
三。编写相关代码,
1.编写签章类,收集签章相关信息
ample.itext.utils;
import pdf.PdfSignatureAppearance;
import pdf.curity.MakeSignature;
import lombok.Data;
import java.curity.PrivateKey;
import Certificate;
@Data
public class SignatureInfo {
private String reason; //理由
private String location;//位置
private String digestAlgorithm;//摘要类型
private String imagePath;//图章路径
private String fieldName;//表单域名称
完美的意思private Certificate[] chain;//证书链
private PrivateKey pk;//私钥
private int certificationLevel = 0; //批准签章
private PdfSignatureAppearance.RenderingMode renderingMode;//表现形式:仅描述,仅图⽚,图⽚和描述,签章者和描述private MakeSignature.CryptoStandard subfilter;//⽀持标准,CMS,
CADES
}
2.编写⼯具类,红⾊字体为完成签章的主体逻辑,以ByteArrayOutputStream充当输出流是为了完成多次签章,期间不会⽣成临时⽂件。MakeSignature.signDetached()⽅法每调⽤⼀次,必须重新获取
PdfSignatureAppearance对象,因为分析源码⽅法可知,该⽅法调⽤时,appearance对象的preClod参数会被置为fal。ample.itext.utils;
import DocumentException;
import Image;
import pdf.PdfReader;
import pdf.PdfSignatureAppearance;
import pdf.PdfStamper;
import pdf.curity.BouncyCastleDigest;
import pdf.curity.DigestAlgorithms;
import pdf.curity.ExternalDigest;
import pdf.curity.ExternalSignature;
import pdf.curity.MakeSignature;
import pdf.curity.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.curity.GeneralSecurityException;
import java.curity.KeyStore;
import java.curity.PrivateKey;
import Certificate;
public class ItextUtil {
public static final char[] PASSWORD = "123456".toCharArray();//keystory密码
/**
* 单多次签章通⽤
* 单多次签章通⽤
* @param src
* @param target
* @param signatureInfos
* @throws GeneralSecurityException
* @throws IOException
* @throws DocumentException
*/
public void sign(String src, String target, signatureInfos){
InputStream inputStream = null;
FileOutputStream outputStream = null;
ByteArrayOutputStream result = new ByteArrayOutputStream();
try {
inputStream = new FileInputStream(src);
for (SignatureInfo signatureInfo : signatureInfos) {
ByteArrayOutputStream tempArrayOutputStream = new ByteArrayOutputStream();
PdfReader reader = new PdfReader(inputStream);
//创建签章⼯具PdfStamper ,最后⼀个boolean参数是否允许被追加签名
PdfStamper stamper = ateSignature(reader, tempArrayOutputStream, '\0', null, true);
// 获取数字签章属性对象
PdfSignatureAppearance appearance = SignatureAppearance();
appearance.Reason());
appearance.Location());
//设置签名的签名域名称,多次追加签名的时候,签名预名称不能⼀样,图⽚⼤⼩受表单域⼤⼩影响(过⼩导致压缩)
appearance.FieldName());
//读取图章图⽚
Image image = ImagePath());
appearance.tSignatureGraphic(image);
appearance.CertificationLevel());
//设置图章的显⽰⽅式,如下选择的是只显⽰图章(还有其他的模式,可以图章和签名描述⼀同显⽰)
appearance.RenderingMode());
// 摘要算法
ExternalDigest digest = new BouncyCastleDigest();
// 签名算法
ExternalSignature signature = new Pk(), DigestAlgorithm(), null);
// 调⽤itext签名⽅法完成pdf签章
MakeSignature.signDetached(appearance, digest, signature, Chain(), null, null, null, 0, Subfilter()); //定义输⼊流为⽣成的输出流内容,以完成多次签章的过程
inputStream = new ByteArray());
result = tempArrayOutputStream;
}
outputStream = new FileOutputStream(new File(target));
outputStream.ByteArray());
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(null!=outputStream){
outputStream.clo();
}
if(null!=inputStream){
inputStream.clo();
}
if(null!=result){
result.clo();
}
不停的近义词} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
节日习俗作文try {
ItextUtil app = new ItextUtil();
ItextUtil app = new ItextUtil();
//将证书⽂件放⼊指定路径,并读取keystore ,获得私钥和证书链
String pkPath = Class().getResource("/template/zhengshu.p12").getPath();
KeyStore ks = Instance("PKCS12");
ks.load(new FileInputStream(pkPath), PASSWORD);
String alias = ks.alias().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
String src = Class().getResource("/template/check.pdf").getPath();
//封装签章信息
SignatureInfo info = new SignatureInfo();
info.tReason("理由");
info.tLocation("位置");
info.tPk(pk);
info.tChain(chain);
info.tCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
info.tDigestAlgorithm(DigestAlgorithms.SHA1);
info.tFieldName("sig1");
info.Class().getResource("/template/yinzhang.png").getPath()); info.tRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
SignatureInfo info1 = new SignatureInfo();
info1.tReason("理由1");
info1.tLocation("位置1");
世界十大城市排名info1.tPk(pk);
info1.tChain(chain);
info1.tCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
info1.tDigestAlgorithm(DigestAlgorithms.SHA1);
info1.tFieldName("sig2");
info1.Class().getResource("/template/yinzhang.png").getPath()); info1.tRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
app.sign(src, "D://sign.pdf", info,info1);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
⾄此,电⼦签章的代码整理完毕。