iText 在 java 中验证 pdf 的完整性
iText verify integrity of a pdf in java
我的网络服务器生成一个 pdf 文件,对其进行签名,然后将其提供给客户。客户端对其进行多次签名(使用 Adobe Pro 使用不同的令牌),然后将其上传回服务器。
我想让服务器验证是否是之前服务器生成的pdf。我读到当应用多个签名时哈希值会改变。如何使用 iText 轻松进行此验证?
同一 PDF 中的多个集成签名通过 增量更新 应用,如果操作正确,请参见。 this answer 在信息安全堆栈交换上:
因此,虽然在某种程度上你读到的是真的
I read that the hash is changed when multiple signatures are applied.
(事实上,整个文件的散列值 会发生变化,除非发生极不可能的冲突),字节的散列值 您的初始签名适用于 保留并可以从文档中检索。
因此,根据您要检查的内容以及您仍然拥有的信息,有以下明显的选择:
比较初始版本
My web server generates a pdf, signs it, and give it to the client
如果您仍然将初始签名的 PDF 存储在某个地方(例如在数据库中)并且您想要检查客户端上传回您的 PDF 是否基于该 PDF,您需要做的就是检查是否客户端的 PDF 字节流以您存储的 PDF 的字节开始。
这不需要额外使用任何加密函数或特定于 PDF 的 API,只需比较字节或块。
检查签名
My web server generates a pdf, signs it, and give it to the client
如果您没有将初始签名的 PDF 存储在任何地方,或者您只想检查客户端上传回您的 PDF 是否基于您签名的许多可能的基础 PDF 之一,则无法进行直接修订比较或非常耗费资源。
在这种情况下你应该检查文档的初始签名是否
- 有效且
- 已由您的服务器创建。
检查签名有效性
有很多关于如何检查 PDF 中签名完整性的示例,例如
public PdfPKCS7 verifySignature(AcroFields fields, String name) throws GeneralSecurityException, IOException {
System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
PdfPKCS7 pkcs7 = fields.verifySignature(name);
System.out.println("Integrity check OK? " + pkcs7.verify());
return pkcs7;
}
public void verifySignatures(String path) throws IOException, GeneralSecurityException {
System.out.println(path);
PdfReader reader = new PdfReader(path);
AcroFields fields = reader.getAcroFields();
ArrayList<String> names = fields.getSignatureNames();
for (String name : names) {
System.out.println("===== " + name + " =====");
verifySignature(fields, name);
}
System.out.println();
}
(C5_01_SignatureIntegrity.java 来自 iText 数字签名白皮书)
对于您的任务,您实际上可以简单地限制自己只检查第一个签名,但也检查其他签名可能也是一个好主意。
检查签名证书
要检查您的服务器是否已创建初始签名,我们假设您的 Web 服务器使用专用于此任务的 X509 证书(或一组已知的此类证书)对这些 PDF 进行签名。
您可以通过 PdfPKCS7
对象的 getSigningCertificate
方法检索用于创建初始签名的证书,您从第一个签名的 verifySignature
调用中检索到该对象。您所要做的就是检查证书是否是您专用于此任务的一个证书(或一组证书中的一个)。
我的网络服务器生成一个 pdf 文件,对其进行签名,然后将其提供给客户。客户端对其进行多次签名(使用 Adobe Pro 使用不同的令牌),然后将其上传回服务器。
我想让服务器验证是否是之前服务器生成的pdf。我读到当应用多个签名时哈希值会改变。如何使用 iText 轻松进行此验证?
同一 PDF 中的多个集成签名通过 增量更新 应用,如果操作正确,请参见。 this answer 在信息安全堆栈交换上:
因此,虽然在某种程度上你读到的是真的
I read that the hash is changed when multiple signatures are applied.
(事实上,整个文件的散列值 会发生变化,除非发生极不可能的冲突),字节的散列值 您的初始签名适用于 保留并可以从文档中检索。
因此,根据您要检查的内容以及您仍然拥有的信息,有以下明显的选择:
比较初始版本
My web server generates a pdf, signs it, and give it to the client
如果您仍然将初始签名的 PDF 存储在某个地方(例如在数据库中)并且您想要检查客户端上传回您的 PDF 是否基于该 PDF,您需要做的就是检查是否客户端的 PDF 字节流以您存储的 PDF 的字节开始。
这不需要额外使用任何加密函数或特定于 PDF 的 API,只需比较字节或块。
检查签名
My web server generates a pdf, signs it, and give it to the client
如果您没有将初始签名的 PDF 存储在任何地方,或者您只想检查客户端上传回您的 PDF 是否基于您签名的许多可能的基础 PDF 之一,则无法进行直接修订比较或非常耗费资源。
在这种情况下你应该检查文档的初始签名是否
- 有效且
- 已由您的服务器创建。
检查签名有效性
有很多关于如何检查 PDF 中签名完整性的示例,例如
public PdfPKCS7 verifySignature(AcroFields fields, String name) throws GeneralSecurityException, IOException {
System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
PdfPKCS7 pkcs7 = fields.verifySignature(name);
System.out.println("Integrity check OK? " + pkcs7.verify());
return pkcs7;
}
public void verifySignatures(String path) throws IOException, GeneralSecurityException {
System.out.println(path);
PdfReader reader = new PdfReader(path);
AcroFields fields = reader.getAcroFields();
ArrayList<String> names = fields.getSignatureNames();
for (String name : names) {
System.out.println("===== " + name + " =====");
verifySignature(fields, name);
}
System.out.println();
}
(C5_01_SignatureIntegrity.java 来自 iText 数字签名白皮书)
对于您的任务,您实际上可以简单地限制自己只检查第一个签名,但也检查其他签名可能也是一个好主意。
检查签名证书
要检查您的服务器是否已创建初始签名,我们假设您的 Web 服务器使用专用于此任务的 X509 证书(或一组已知的此类证书)对这些 PDF 进行签名。
您可以通过 PdfPKCS7
对象的 getSigningCertificate
方法检索用于创建初始签名的证书,您从第一个签名的 verifySignature
调用中检索到该对象。您所要做的就是检查证书是否是您专用于此任务的一个证书(或一组证书中的一个)。