In Itext 7, how to sign a pdf with 2 steps?

前端 未结 1 1216
北荒
北荒 2020-12-22 04:03

Following the answers given in this previous question : In Itext 7, how to get the range stream to sign a pdf?, i\'ve tried to reimplement the two steps signing method worki

相关标签:
1条回答
  • 2020-12-22 05:02

    why is the result of this step invalid

    Because you essentially discovered a bug... ;)

    Your sample input file has one feature which triggers the bug: It is compressed using object streams.

    When iText manipulates such a file, it also tries to put as many objects as possible into object streams. Unfortunately it also does so with the signature dictionary. This is unfortunate because after writing the whole file it tries to enter some information (which are not available before) into this dictionary which damages the compressed object stream.


    What you can do...

    You can either

    • wait for iText development to fix this issue - I assume this won't take too long but probably you don't have the time to wait; or
    • convert the file to sign into a form which does not use object streams - this can be done using iText itself but probably you cannot accept the file growth this means, or probably the files already are signed which forbids any such transformation; or
    • patch iText 7 to force the signature dictionary not to be added to an object stream - it is a trivial patch but you probably don't want to used patched libraries.

    The patch mentioned above indeed is trivial, the method PdfSigner.preClose(Map<PdfName, Integer>) contains this code:

    if (certificationLevel > 0) {
        // add DocMDP entry to root
        PdfDictionary docmdp = new PdfDictionary();
        docmdp.put(PdfName.DocMDP, cryptoDictionary.getPdfObject());
        document.getCatalog().put(PdfName.Perms, docmdp); // TODO: setModified?
    }
    
    document.close();
    

    The cryptoDictionary.getPdfObject()) is the signature dictionary I mentioned above. During document.close() it is added to an object stream unless it has been written to the output before. Thus, you simply have to add a call to flush that object right before that close call and by parameter make clear that it shall not be added to an object stream:

    cryptoDictionary.getPdfObject().flush(false);
    

    With that patch in place, the PDFs your code returns are not damaged as above anymore.


    As an aside, iText 5 does contain a similar line in the corresponding PdfSignatureAppearance.preClose(HashMap<PdfName, Integer>) right above the if block corresponding to the if block above. It seems to have been lost during refactoring to iText 7.

    0 讨论(0)
提交回复
热议问题