iText验证java中pdf的完整性

时间:2017-05-01 19:45:58

标签: java pdf itext signature integrity

我的网络服务器会生成一个pdf,对其进行签名并将其提供给客户端。客户端多次签名(使用Adobe Pro使用不同的令牌),然后将其上传回服务器。

我希望服务器验证它是否是以前由服务器生成的pdf。我读到在应用多个签名时更改了哈希。如何使用iText轻松验证?

1 个答案:

答案 0 :(得分:4)

如果正确完成,同一PDF中的多个集成签名将通过增量更新应用,参见信息安全堆栈交换this answer

incremental updates with signatures

因此,在某种程度上你读到的是真的

  

我读到在应用多个签名时更改了哈希值。

(实际上,整个文件的哈希值会发生变化,除非你的碰撞极不可能),你的初始签名的字节的哈希值仍然适用于,可以是从文档中检索。

因此,根据您要检查的内容以及您仍然拥有的信息,有以下明显选项:

比较初始修订

  

我的网络服务器生成pdf,签名并将其提供给客户

如果您仍然将某个初始签名PDF存储在某个地方(例如在数据库中),并且您想要检查客户端上传回给您的PDF是否基于该PDF,那么您需要做的就是检查客户端和#39;的PDF字节流以您存储的PDF字节开头。

这不需要额外使用加密函数或PDF特定API,只需比较它们的字节或块。

检查签名

  

我的网络服务器生成pdf,签名并将其提供给客户

如果您没有将初始签名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();
}

(来自iText数字签名白皮书的C5_01_SignatureIntegrity.java

对于你的任务,你实际上可以简单地限制自己只检查第一个签名,但检查其他签名也可能是个好主意。

检查签名证书

要检查服务器是否已创建初始签名,请假设您的Web服务器使用专用于此任务的X509证书(或一组已知此类证书)对这些PDF进行签名。

您可以使用从getSigningCertificate调用第一个签名中检索到的PdfPKCS7对象的方法verifySignature来检索用于创建初始签名的证书。您所要做的就是检查证书是否是您专门用于此任务的一个证书(或一组证书)。