实例代码地址:https://github.com/haoxiaoyong1014/testarea-itext5
验证签名模块代码位置:
testarea-itext5/src/test/java/mkl/testarea/itext5/signature/VerifySignature.java
一,实际需求:
用户上传带有签署证书的pdf文件,我们进行验证证书的真实性,有效性以及是否篡改过
二,pom.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mkl.testarea.itext5</groupId>
<artifactId>testarea-itext5</artifactId>
<packaging>jar</packaging>
<name>Test area for public iText v5 issues on stackoverflow etc</name>
<version>5.5.14-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerVersion>1.8</compilerVersion>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<junit.version>4.7</junit.version>
<itextpdf.version>${project.version}</itextpdf.version>
</properties>
<dependencies>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-xtra</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-pdfa</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.49</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.49</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.19</version>
</dependency>
</dependencies>
</project>
三,测试准备
将带有签署证书的pdf文件放到项目中的
testarea-itext5\src\test\resources\mkl\testarea\itext5\signature目录下,当然放到这个目录下只是测试使用,实际开发中pdf文件是用户上传过来的,如果你还没有签署证书的pdf文件的话,你可到项目中的 testarea-itext5/src/test/java/mkl/testarea/itext5/signature/CreateSignature.java 这个类就是将证书签署到pdf文件中,项目中有生成好的证书(demo-rsa2048.ks),你只需要运行一下测试方法即可,如果你不想运行测试方法也可以,
testarea-itext5\src\test\resources\mkl\testarea\itext5\signature目录下我放了带有证书的pdf文件,你只要运行以下代码就可以实现验签,向pdf中签署证书今天不做讨论,在我下篇博客中说明。接下来咱们继续说明验签过程
四:验签代码
public static void setUp() throws Exception {
BouncyCastleProvider bcp = new BouncyCastleProvider();
//Security.addProvider(bcp);
Security.insertProviderAt(bcp, 1);
}
public void testVerifyTestMGomez() throws Exception {
System.out.println("\n\nTestMGomez.pdf\n==============");
setUp();
try (InputStream resource = getClass().getResourceAsStream("TestMGomez.pdf")) {
PdfReader reader = new PdfReader(resource);
AcroFields acroFields = reader.getAcroFields();
List<String> names = acroFields.getSignatureNames();
for (String name : names) {
System.out.println("Signature name: " + name);
System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name));
PdfPKCS7 pk = acroFields.verifySignature(name);
System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate()));
System.out.println("Document verifies: " + pk.verify());
}
}
System.out.println();
Field rsaDataField = PdfPKCS7.class.getDeclaredField("RSAdata");
rsaDataField.setAccessible(true);
try (InputStream resource = getClass().getResourceAsStream("TestMGomez.pdf")) {
PdfReader reader = new PdfReader(resource);
AcroFields acroFields = reader.getAcroFields();
List<String> names = acroFields.getSignatureNames();
for (String name : names) {
System.out.println("Signature name: " + name);
System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name));
PdfPKCS7 pk = acroFields.verifySignature(name);
System.out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate()));
Object rsaDataFieldContent = rsaDataField.get(pk);
if (rsaDataFieldContent != null && ((byte[]) rsaDataFieldContent).length == 0) {
System.out.println("Found zero-length encapsulated content: ignoring");
rsaDataField.set(pk, null);
}
System.out.println("Document verifies: " + pk.verify());
}
}
}
其中 TestMGomez.pdf 就是带有签署证书的pdf文件
五,测试结果:
打印的结果中包含 签名值,签名是否涵盖整个文档,证书所有者,验签结果