2
votes

Is it possible to add additional page to the signed PDF and sign it again without breaking the first signature.

I read in the adobe documentation under incremental updates that it may be possible.

However, I'm not sure if that applies to all the content or just the Annotations (commenting), form fill-in and digital signatures.

I tried to do this by using Apache PDFBox in Java, by signing the document, then loading it, appending the page to it, saving it using saveIncremental() and signing it again.

However, the first signature gets invalidated.

Here is my generateTest method that generates the new PDF:

public byte[] generateTest(InputStream requestPdfIn) throws IOException {

    // Create a document and add a page to it
    // PDDocument document = new PDDocument();
    PDDocument document = PDDocument.load(requestPdfIn);
    PDPage page = new PDPage(PDRectangle.A4);
    document.addPage(page);     

    COSBase item = document.getPages().getCOSObject().getItem(COSName.KIDS);
    ((COSUpdateInfo) item).setNeedToBeUpdated(true);
    COSArray kids = (COSArray) item;
    kids.setNeedToBeUpdated(true);
    ((COSUpdateInfo) kids.get(0)).setNeedToBeUpdated(true);

    document.getPage(0).getCOSObject().setNeedToBeUpdated(true);
    page.getCOSObject().setNeedToBeUpdated(true);
    document.getPages().getCOSObject().setNeedToBeUpdated(true);

    COSDictionary dict = page.getCOSObject();
    while (dict.containsKey(COSName.PARENT)) {
        COSBase parent = dict.getDictionaryObject(COSName.PARENT);
        if (parent instanceof COSDictionary) {
            dict = (COSDictionary) parent;
            dict.setNeedToBeUpdated(true);
        }
    }

    document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
    //document.getDocumentCatalog().getStructureTreeRoot().getCOSObject().setNeedToBeUpdated(true);

    // Save the results and ensure that the document is properly closed:
    ByteArrayOutputStream confirmationPdfOut = new ByteArrayOutputStream();
    document.saveIncremental(confirmationPdfOut);
    document.close();

    return confirmationPdfOut.toByteArray();

}

I found in this post that all the COSObjects need to have a flag needToBeUpdated set to true.

However, that still doesn't help when trying to add another page to the document, as the first signature gets invalidated when I try to verify the signature using Acrobat Reader.

Is it even possible? Is it possible with the PDFBox?

1

1 Answers

4
votes

No, it is not possible. Adding pages to an already signed PDF is not allowed.

In detail

I read in the adobe documentation under incremental updates that it may be possible.

Indeed it is possible to add changes to a PDF without touching the former revision. Thus, if that former revision was signed, the signature mathematically remains valid, it still signs the correct hash value.

But the PDF specification and its main interpretation (by Adobe that is) contain additional restrictions, cf. this stack overflow answer. As you find there at most the following changes are allowed to signed documents:

  • Adding signature fields
  • Adding or editing annotations
  • Supplying form field values
  • Digitally signing

At least Adobe Acrobat (Reader) does test for such changes in addition to the check for mathematical validity even if numerous other validation services don't.

Thus, your task to add additional page to the signed PDF and sign it again without breaking the first signature cannot be implemented.