Search code examples
securitypdfpdfboxdigital-signatureiso-32000

pdfbox - How to incrementally sign updated document or changes


I have some questions wrt pdfbox.

  1. I want to sucessively sign a document that is subject to changes, e.g. a) originalPdf (signed by X), b) an image is added to the pdf (then signed by person Y), etc., such that the signatures are all valid. How can I reach that with pdfbox, if possible? I tried several things (e.g. with saveIncremental) but they did not give the intended result.
  2. Or do I need to define empty fields beforehand and allow them to be updated with images such that signatures are valid? Is this performed with Annotations, if yes, how could we realize that?

Any helpful tips or code references in the public domain would be very helpful. Thanks.

.... 
contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true); 
PDImageXObject pdImage = PDImageXObject.createFromFile("C:/logo.png", doc); 
....  
page.getResources().getCOSObject().getCOSDictionary(COSName.XOBJECT).setNeedToBeUpdated(true); 
page.getCOSObject().setNeedToBeUpdated(true); 
page.getResources().getCOSObject().setNeedToBeUpdated(true);    
doc.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
doc.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true); 
doc.saveIncremental(fos);

Solution

  • Only a small set of changes is allowed to signed documents, see here for some details. So indeed, you cannot change page contents after signing, and whether or not you can fill form fields or even use arbitrary annotations depends on the signature type of the original signature.

    If the signature(s) do allow adding annotations, though, i.e. if there only are approval (non-certification) signatures or at most a certification signature with annotations, form fill-in, and digital signatures allowed, you can add images in annotations.

    With PDFBox you can add an annotation showing an image in an incremental update like this:

    PDDocument document = ...;
    PDImageXObject image = ...;
    OutputStream result = ...;
    
    PDAppearanceStream appearanceStream = new PDAppearanceStream(document);
    appearanceStream.setBBox(new PDRectangle(1, 1));
    appearanceStream.setResources(new PDResources());
    try (   PDPageContentStream contentStream = new PDPageContentStream(document, appearanceStream) ) {
        contentStream.drawImage(image, new Matrix());
    }
    
    PDAppearanceDictionary appearance = new PDAppearanceDictionary();
    appearance.setNormalAppearance(appearanceStream);
    
    PDAnnotationRubberStamp stamp = new PDAnnotationRubberStamp();
    stamp.setLocked(true);
    stamp.setLockedContents(true);
    stamp.setPrinted(true);
    stamp.setReadOnly(true);
    stamp.setAppearance(appearance);
    stamp.setIntent("StampImage");
    stamp.setRectangle(new PDRectangle(200, 500, 100, 100));
    
    PDPage page = document.getPage(0);
    page.getAnnotations().add(stamp);
    
    Set<COSDictionary> objectsToWrite = new HashSet<>();
    objectsToWrite.add(page.getCOSObject());
    
    document.saveIncremental(result, objectsToWrite);
    

    (AddToSignedFile test testAddImageAnnotation)

    I here used a feature available in the development head towards 3.0.0, the saveIncremental overload with a second argument that accepts a collection of dictionaries to save. If you are working with an earlier version, you may instead have to mark a path of objects from the document catalog to the page object for inclusion in the incremental update using setNeedToBeUpdated.


    If the signature(s) don't allow adding annotations, though, but do allow form editing, i.e. if there is a certification signature with form fill-in and digital signatures allowed, you can at least fill in form fields. This in particular may include setting the appearance of a pushbutton to an image of your choice as Adobe regularly mis-uses pushbuttons as pseudo image-fields. This of course means that you need to have a field prepared for each desired later addition.

    If the signatures don't even allow that, i.e. if there is a certification signature with no changes allowed, or if there are no open form fields available for your additions, you're out of luck.

    As an aside, since PDF 2.0 the certification level can also be made stricter by an entry in the signature locking dictionary of an approval signature. You may have to consider this in the cases above...