iText verify integrity of a pdf in java

廉价感情. 提交于 2019-12-14 03:58:56

问题


My web server generates a pdf, signs it, and give it to the client. The client sign it multiple times (with different tokens using Adobe Pro) and then upload it back to the server.

I want the server to verify if it is the pdf that was previously generated by the server. I read that the hash is changed when multiple signatures are applied. How can do this verification easily with iText ?


回答1:


Multiple integrated signatures in the same PDF are applied by means of incremental updates if done properly, cf. this answer on Information Security Stack Exchange:

Thus, while in a way it is true what you read

I read that the hash is changed when multiple signatures are applied.

(indeed, the hash of the whole file changes unless you have an extremely unlikely collision), the hash of the bytes your initial signature applies to remains and can be retrieved from the document.

So depending on what you want to check and what information you still have, there are these obvious options:

Comparing the initial revision

My web server generates a pdf, signs it, and give it to the client

If you still have that initial signed PDF stored somewhere (e.g. in a database) and you want to check whether the PDF the client uploaded back to you is based on that very PDF, all you need to do is check whether the client's PDF byte stream starts with the bytes of the PDF you stored.

This does not require any extra use of cryptographic functions or PDF specific APIs, merely a comparison of bytes or blocks of them.

Checking the signature

My web server generates a pdf, signs it, and give it to the client

If you don't have that initial signed PDF stored anywhere or you only want to check whether the PDF the client uploaded back to you is based on one of many possible base PDFs signed by you, direct revision comparison is impossible or very resource intensive.

In this case you should check whether the initial signature of the document

  • is valid and
  • has been created by your server.

Checking the signature validity

There are many examples on how to check the integrity of signatures in a PDF, e.g.

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 from the iText digital signatures white paper)

For your task you actually can simply restrict yourself to checking the first signature only but checking the other ones, too, might also be a good idea.

Checking the signature certificate

To check whether the initial signature has been created by your server, let's assume your web server signs these PDFs using a X509 certificate dedicated to this task (or a known set of such certificates).

You can retrieve the certificate using which the initial signature was created with the method getSigningCertificate of the PdfPKCS7 object you retrieve from the verifySignature call for the first signature. All you have to do is check whether the certificate is the one certificate (or one of the set of certificates) you dedicated for this task.



来源:https://stackoverflow.com/questions/43725444/itext-verify-integrity-of-a-pdf-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!