PDFBox - abrir e salvar um pdf assinado invalida minha assinatura

Estou tentando aprender a usar o pdfBox do Apache para lidar com documentos assinados digitalmente para o trabalho. Durante o teste, criei um documento pdf completamente vazio.

Então, assinei o documento através do Adobe Reader usando a função assinar com certificado.

Tentei abrir, salvar e fechar o arquivo assinado com o pdfBox sem nenhuma modificação. No entanto, uma vez que abro o arquivo no Adobe, os arquivos não são mais válidos.

A Adobe me diz: "Existem erros na formatação ou nas informações contidas nesta assinatura (informações de suporte: dados ilegais do SigDict / Contents)"

Como não modifiquei o conteúdo do arquivo, intuitivamente não deveria ter havido problemas e a assinatura ainda deve ser válida, no entanto, esse não é o caso e não sei quais são as soluções (o Google não produziu resultados).

Como eu crio o documento:

@Test
public void createEmptyPDF() throws IOException {
    String path = "path to file";
    PDDocument document = new PDDocument();
    PDPage page = new PDPage();
    document.addPage(page);
    document.save(path);
    document.close();
}

Eu assino com o Adobe e passo por:

 @Test
public void copySignedDocument() throws IOException {
    String path = "path to file";
    File file = new File(path);
    PDDocument document = PDDocument.load(file);
    document.save(file);
    document.close();

    //just opening and saving the file invalidates the signatures
}

Estou realmente sem saber por que isso não funciona. Qualquer ajuda seria ótimo!

EDITAR:

Então, eu fiz algumas investigações e parece que a atualização de um documento assinado existente (adicionando anotações ou preenchendo formulários) ainda não foi implementada no PDFBox 2.0.1 e está programada para ocorrer nas versões 2.1 (no entanto, nenhuma data de lançamento foi especificada). Mais Informaçõesaqui eaqui.

No entanto, parece possível adicionar anotações em documentos assinados com o IText sem invalidar a assinatura usando o PDFStamper,desta pergunta

EDIÇÃO 2: Código para adicionar um carimbo a um documento e salvá-lo gradualmente:

 @Test
public void stampSignedDocument() throws IOException {
    File file = new File("path to file");
    PDDocument document = PDDocument.load(file);
    File image = new File("path to image to be added to annotation");
    PDPage page = document.getPage(0);
    List<PDAnnotation> annotations = page.getAnnotations();
    PDImageXObject ximage = PDImageXObject.createFromFileByContent(image, document);

    //stamp
    PDAnnotationRubberStamp stamp = new PDAnnotationRubberStamp();
    stamp.setName("testing rubber stamp");
    stamp.setContents("this is a test");
    stamp.setLocked(true);
    stamp.setReadOnly(true);
    stamp.setPrinted(true);

    PDRectangle rectangle = createRectangle(100, 100, 100, 100, 100, 100);
    PDFormXObject form = new PDFormXObject(document);
    form.setResources(new PDResources());
    form.setBBox(rectangle);
    form.setFormType(1);

    form.getResources().add(ximage);
    PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
    PDAppearanceDictionary appearance = new PDAppearanceDictionary(new COSDictionary());
    appearance.setNormalAppearance(appearanceStream);
    stamp.setAppearance(appearance);
    stamp.setRectangle(rectangle);
    PDPageContentStream stream = new PDPageContentStream(document, appearanceStream);
    Matrix matrix = new Matrix(100, 0, 0, 100, 100, 100);
    stream.drawImage(ximage, matrix);
    stream.close();
    //close and save   
    annotations.add(stamp);
    page.getCOSObject().setNeedToBeUpdated(true);
    OutputStream os = new FileOutputStream(file);
    document.saveIncremental(os);
    document.close();
    os.close();
}

O código acima não invalida minha assinatura, mas não salva a anotação que adicionei.

Conforme sugerido, configurei o sinalizador NeedToBeUpdated como true para a lista de anotações, página e anotações adicionada (espero que eu tenha feito o último corretamente):

    stamp.getCOSObject().setNeedToBeUpdated(true);
    COSArrayList<PDAnnotation> list = (COSArrayList<PDAnnotation>) annotations;
    COSArrayList.converterToCOSArray(list).setNeedToBeUpdated(true);
    page.getCOSObject().setNeedToBeUpdated(true);
    document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);

A anotação ainda não foi salva, então estou obviamente perdendo alguma coisa.

EDIT 3:

Este é o meu método atual para adicionar uma anotação:

    @Test
public void stampSignedDocument() throws IOException {
    File file = new File(
            "E:/projects/eSign/g2digitalsignature/G2DigitalSignatureParent/G2DigitalSignatureTest/src/test/resources/pdfBoxTest/empty.pdf");
    PDDocument document = PDDocument.load(file);
    File image = new File(
            "E:/projects/eSign/g2digitalsignature/G2DigitalSignatureParent/G2DigitalSignatureTest/src/test/resources/pdfBoxTest/digitalSign.png");
    PDPage page = document.getPage(0);
    List<PDAnnotation> annotations = page.getAnnotations();
    PDImageXObject ximage = PDImageXObject.createFromFileByContent(image, document);

    //stamp
    PDAnnotationRubberStamp stamp = new PDAnnotationRubberStamp();
    stamp.setName("testing rubber stamp");
    stamp.setContents("this is a test");
    stamp.setLocked(true);
    stamp.setReadOnly(true);
    stamp.setPrinted(true);

    PDRectangle rectangle = createRectangle(100, 100, 100, 100, 100, 100);
    PDFormXObject form = new PDFormXObject(document);
    form.setResources(new PDResources());
    form.setBBox(rectangle);
    form.setFormType(1);

    form.getResources().getCOSObject().setNeedToBeUpdated(true);
    form.getResources().add(ximage);
    PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
    PDAppearanceDictionary appearance = new PDAppearanceDictionary(new COSDictionary());
    appearance.setNormalAppearance(appearanceStream);
    stamp.setAppearance(appearance);
    stamp.setRectangle(rectangle);
    PDPageContentStream stream = new PDPageContentStream(document, appearanceStream);
    Matrix matrix = new Matrix(100, 0, 0, 100, 100, 100);
    stream.drawImage(ximage, matrix);
    stream.close();
    //close and save   
    annotations.add(stamp);

    appearanceStream.getCOSObject().setNeedToBeUpdated(true);
    appearance.getCOSObject().setNeedToBeUpdated(true);
    rectangle.getCOSArray().setNeedToBeUpdated(true);
    stamp.getCOSObject().setNeedToBeUpdated(true);
    form.getCOSObject().setNeedToBeUpdated(true);
    COSArrayList<PDAnnotation> list = (COSArrayList<PDAnnotation>) annotations;
    COSArrayList.converterToCOSArray(list).setNeedToBeUpdated(true);
    document.getPages().getCOSObject().setNeedToBeUpdated(true);
    page.getCOSObject().setNeedToBeUpdated(true);
    document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);

    OutputStream os = new FileOutputStream(file);
    document.saveIncremental(os);
    document.close();
    os.close();

}

Quando adiciono uma anotação usando-a em um documento não assinado, a anotação é adicionada e fica visível. No entanto, ao usá-lo em um documento assinado, a anotação não aparece.

Abri o arquivo pdf no bloco de notas ++ e descobri que a anotação parece ter sido adicionada desde que o encontrei, assim como o restante do código referente à anotação:

<<
/Type /Annot
/Subtype /Stamp
/Name /testing#20rubber#20stamp
/Contents (this is a test)
/F 196
/AP 29 0 R
/Rect [100.0 100.0 200.0 200.0]
>>

No entanto, ele não aparece quando abro o documento no Adobe Reader. Talvez isso tenha mais a ver com os fluxos de aparência do que com a própria anotação?

questionAnswers(2)

yourAnswerToTheQuestion