Search code examples
javaitextdigital-signature

Adding DSS to a pdf makes it invalid


I'm working on a PDF Signer/Validator and I'm using Itext7.

First I sign the pdf using the signDetached method from Itext7 :

signer.signDetached(digest, pks, chain, crlClients, ocspClient, tsaClient, 0, signatureType);

Second I add LTV info using these lines of code :

PdfReader   reader = new PdfReader(src);
PdfWriter writer = new PdfWriter(dest2);
PdfDocument pdfDoc = new PdfDocument(reader, writer, new 
    StampingProperties().useAppendMode());

LtvVerification v = new LtvVerification(pdfDoc);
SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);

List<String> names = signatureUtil.getSignatureNames();
String sigName = names.get(names.size() - 1);

for (String name : names){
    v.addVerification(name, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
        LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.YES);
}

v.merge();

At this point the file is signed and DSS is added. but when I try to validate the file here where the problem comes, I'm using Itext7 method to verify that the signature covers the whole document :

signatureUtil.signatureCoversWholeDocument(name);

But it keeps failing because the signature does not covers all the document although the file is not altered after signing only the DSS info is added and after more digging I found that the checkWhetherSignatureCoversWholeDocument() method inside the signatureCoversWholeDocument() method is the reason why it fails when it comes to check the byte ranges

this.tokens.getSafeFile().length() == (long)(byteRange[2] + byteRange[3])

This check always fail and that is the reason why it says that the file does not covers all document.

So what is wrong here, am I missing something ? All I need is to sign the file, add DSS and be able to validate this signature that it covers all the document .


Solution

  • I Solved it by using signDeferred method instead of signDetached.

    The problem occurs when trying to add DSS to the pdf dictionary after signing because it's considered as Editing the file after signing it so the signature does not covers the whole document anymore.

    The solution was to use signDeferred method, It works by first use signExternalContainer method to modify the pdf dictionary and leave a blank placeholder for the signature to be added lately, then use the signDeferred method to fill this blank placeholder with the signature.

    Check the official IText7 documentation for the signDeferred method : IText7 signDeferred

    The documentation shows how to sign using signDeferred but without adding crl or timestamp to the DSS so you can check my implementation here for adding crl and embedded timestamp with signDeferred method.