Search code examples
javapdfitextsignatureintegrity

iText verify integrity of a pdf in java


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 ?


Solution

  • 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:

    incremental updates with signatures

    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.