iText7 multiple signature

2019-08-21 03:05发布

问题:

I want to do multiple signatures in a pdf document with iText7 , but the problem is when I have once sign , it works . If I sign twice , the first signature is invalid . It looks like this :

unsigned PDF

signed PDF

and here is my code:

@Test
public void testMutiSign() {

    iTextSignerUtil1.SignMultPDF(getBytes(unsignedPath), destPath1);

    iTextSignerUtil2.SignMultPDF(getBytes(destPath1), destPath2);

}


 IExternalSignatureContainer externalP7DetachSignatureContainer = new IExternalSignatureContainer() {
    @Override
    public byte[] sign(InputStream data) throws GeneralSecurityException {


        //byte[] hashData = HashUtil.hash(data , "SHA256");

        byte signData = null;
        signData = signUtil.signP7DetachData(data);

        return signData;

    }


    @Override
    public void modifySigningDictionary(PdfDictionary signDic) {
        signDic.put(PdfName.Filter, PdfName.Adobe_PPKLite);
        signDic.put(PdfName.SubFilter, PdfName.Adbe_pkcs7_detached);
    }
};


public void SignMultPDF(byte[] pdfFile , String destPath , String name , String fname , String value){

    boolean success = false;

    int estimatedSize = 300000;

    while (!success) {
        try {

            PdfReader pdfReader = new PdfReader(new ByteArrayInputStream(pdfFile));
            PdfSigner pdfSigner = new PdfSigner(pdfReader, new FileOutputStream(destPath), true);

          pdfSigner.signExternalContainer(externalP7DetachSignatureContainer, estimatedSize);

            success = true;

        } catch (IOException e) {
            e.printStackTrace();
            estimatedSize += 1000;
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
    }
}

Above is all my sample code .

And one more question , did I miss to create signature field ?

回答1:

The cause of this issue is a quirk of the original file: It has an empty indirect dictionary which it uses both as Info dictionary and as Outlines dictionaries.

Whenever manipulating a PDF iText updates its Info dictionary, in particular the ModDate is likely to change each time.

Thus, during each signing pass the Info dictionary is changed, and as the dictionary object is shared, so is the Outlines dictionary. But changing the Outlines of an already signed PDF is not allowed. Thus, the Info (and Outlines) changes during the creation of the second signature are not allowed and invalidate the first signature.

This file is nearly the same as the original file, the only difference is that it uses different empty dictionaries for Info and Outlines (as there was a currently unused empty indirect dictionary in the file, I merely needed to change the reference of Info or Outlines to this unused object). When signing this file twice, Adobe does not complain anymore.


Is this a bug in iText or in the PDF? I think iText should use a new indirect object number when changing the Info dictionary because such duplicate uses of dictionaries is not generally forbidden in PDFs. But a PDF making use of such duplicate indirect object uses is really asking for trouble. So I think this question brings both an iText issue and an issue in the PDF into the light.