编程语言
首页 > 编程语言> > java – PDFBox – 打开并保存已签名的pdf会使我的签名无效

java – PDFBox – 打开并保存已签名的pdf会使我的签名无效

作者:互联网

我正在努力学习使用Apache的pdfBox来处理数字签名文档的工作.在测试期间,我创建了一个完全空的pdf文档.

然后我使用带证书功能的签名通过Adobe Reader签署了该文档.

我尝试使用pdfBox打开,保存和关闭已签名的文件,而不进行任何修改.但是,一旦我在Adobe中打开文件,文件就不再有效.

Adobe告诉我:“此签名中包含的格式或信息存在错误(支持信息:SigDict / Contents非法数据)”

由于我没有修改文件的内容,直观上应该没有任何问题,签名应该仍然有效,但事实并非如此,我不知道解决方案是什么(谷歌搜索没有产生任何结果).

我如何创建文档:

@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();
}

然后我用adobe签名并通过它:

 @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
}

我真的不知道为什么这不起作用.任何帮助都会很棒!

编辑:

所以我做了一些挖掘,似乎更新现有签名文档(添加注释或填写表格)尚未在PDFBox 2.0.1中实现,并计划在版本2.1中(但是没有指定发布日期).更多信息herehere.

但是,似乎可以使用IText在签名文档上添加注释,而不会使用PDFStamper,from this question使签名无效

编辑2:
用于向文档添加戳记并以增量方式保存的代码:

 @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();
}

上面的代码不会使我的签名无效,但不会保存我添加的注释.

正如所建议的那样,我已经为添加的注释,页面和注释列表设置了NeedToBeUpdated标志为true(我希望我正确地完成了最后一个):

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

注释仍然没有保存,所以我显然遗漏了一些东西.

编辑3:

这是我当前添加注释的方法:

    @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();

}

当我在非签名文档上使用它添加注释时,注释会被添加并且可见.但是,在签名文档上使用它时,不会显示注释.

我在记事本中打开了pdf文件并发现注释似乎已添加,因为我发现这个以及与注释有关的其余代码:

<<
/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]
>>

但是,当我在adobe reader中打开文档时,它不会出现.也许这与外观流有关而不是注释本身?

解决方法:

问题是使用PDDocument.save()会创建一个新文档,从而使签名无效.

使用PDDocument.saveIncremental(…)不会使签名无效,但是它不会更新对文档的任何更改(例如注释或表单填写),它仅用于保存签名.

使用PDFBox 2.0无法更新带注释或表单填写的签名PDF文档,但一旦PDFBox 2.1推出就应该可以.

有关问题的信息:herehere

但是,使用IText的PDFStamper可以解决在签名文档中添加注释而不会使签名失效的问题,如here所示.

标签:adobe,java,pdf,pdfbox,digital-signature
来源: https://codeday.me/bug/20191002/1842233.html