PDFBox - 打开并保存已签名的pdf会使我的签名无效 [英] PDFBox - opening and saving a signed pdf invalidates my signature

查看:624
本文介绍了PDFBox - 打开并保存已签名的pdf会使我的签名无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to learn to use Apache's pdfBox to deal with digitaly signed documents for work. During testing, I created a completely empty pdf document.

然后我使用带证书功能的符号通过Adobe reader签署文档。

I then signed the document through Adobe reader using the sign with certificate function.

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

I tried to open, save and close the signed file with pdfBox without any modifications. However once I open the file in Adobe the files are no longer valid.

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

Adobe tells me: "There are errors in the formatting or information contained in this signature (support information: SigDict/Contents illegal data)"

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

Since I have not modified the content of the file, intuitively there should not have been any problems and the signature should be still valid, however this is not the case and I don't know what the solutions are (googling yielded no results).

我如何创建文档:

@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签名并传递给它:

I then sign it with adobe and pass it through this:

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

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

I am truly at a loss as to why this does not work. Any help would be great!

编辑:

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

So I did some digging around and it seems that updating an existing signed document (either adding annotations or filling forms) is not yet implemented in PDFBox 2.0.1 and is scheduled to come in versions 2.1 (however no release date has been specified). More information here and here.

然而,似乎可以在IText的签名文件上添加注释而不会使用PDFStamper使签名无效,

However it seems possible to add annotations on signed documents with IText without invalidating the signature using PDFStamper, from this question

编辑2:
为文档添加图章并以增量方式保存的代码:

EDIT 2: Code to add a stamp to a document and save it incrementally:

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

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

The above code doesn't invalidate my signature but doesn't save the annotation that I have added.

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

As suggested I've set the NeedToBeUpdated flag to true for the added annotation, page and annotations list (I hope I did the last one correctly):

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

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

The annotation is still not saved so I'm obviously missing something.

编辑3:

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

This is my current method to add an annotation:

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

}

当我在非签名文档上使用它添加注释时,注释被添加并可见。但是,当在签名文档上使用它时,注释不会出现。

When I add an annotation using it on a non signed document, the annotation gets added and is visible. However when using it on a signed document, the annotation does not appear.

我已经在notepad ++中打开了pdf文件并且发现注释似乎已经添加了我发现这个以及与注释有关的其余代码:

I have opened the pdf file in notepad++ and have found that the annotation seems to have been added since I found this as well as the rest of the code pertaining to the annotation:

<<
/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中打开文档时,它不会出现。也许这与外观流有关,而不是注释本身?

However it does not appear when I open the document in adobe reader. Perhaps this has more to do with the appearance streams than the annotation itself?

推荐答案

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

The problem is that using PDDocument.save() creates a new document and thus invalidates the signature.

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

Using PDDocument.saveIncremental(...) does not invalidate the signature, however it will not update any changes to the document (such as annotations or form filling), it is only used to save a signature.

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

Updating a signed PDF document with annotations or form filling is not yet possible with PDFBox 2.0 but should be possible once PDFBox 2.1 rolls out.

有关问题的信息:此处这里

然而,使用IText的PDFStamper解决了在签名文档中添加注释而不会使签名失效的问题在其他地方

Using IText's PDFStamper however solve the problem of adding annotations to a signed document without invalidating the signature as answered here.

这篇关于PDFBox - 打开并保存已签名的pdf会使我的签名无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆