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
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.
You can either
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.