【问题标题】:pdfbox - How to incrementally sign updated document or changespdfbox - 如何以增量方式签署更新的文档或更改
【发布时间】:2020-12-27 19:48:30
【问题描述】:

我有一些关于 pdfbox 的问题。

  1. 我想连续签署一份可能会发生变化的文件,例如a) originalPdf (由 X 签名), b) 将图像添加到 pdf (然后由人 Y 签名) 等, 这样签名都是有效的。如果可能的话,我怎样才能用 pdfbox 做到这一点?我尝试了几件事(例如使用 saveIncremental),但没有给出预期的结果。
  2. 或者我是否需要预先定义空字段并允许使用图像更新它们以使签名有效?这是否使用 Annotations 执行,如果是,我们如何实现这一点?

任何有用的提示或公共领域的代码参考都会非常有帮助。谢谢。

.... 
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);

【问题讨论】:

  • 您是否尝试过这些示例,哪些没有奏效?
  • 请首先注意,仅允许对已签名文档进行少量更改,有关详细信息,请参阅here。所以确实,签名后不能更改页面内容,是否可以填写表单字段甚至使用任意注释取决于原始签名的签名类型。
  • 我尝试了以下
  • .... 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);
  • 签名无效。根据您的评论@mkl,我如何插入图像,例如作为 AcroForm 或注释,这样插入图像不会使签名无效?有没有例子?谢谢。

标签: security pdf pdfbox digital-signature iso-32000


【解决方案1】:

仅允许对已签名的文档进行少量更改,有关详细信息,请参阅here。所以确实,签名后不能更改页面内容,是否可以填写表单字段甚至使用任意注释取决于原始签名的签名类型。

如果签名确实允许添加注释,即,如果只有批准(非认证)签名或最多一个认证签名允许添加注释、表格填写和数字签名,可以在注解中添加图片。

使用 PDFBox,您可以像这样在增量更新中添加显示图像的注释:

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 测试testAddImageAnnotation)

我在这里使用了 3.0.0 的开发头中可用的功能,saveIncremental 重载,第二个参数接受要保存的字典集合。如果您使用的是早期版本,则可能必须使用 setNeedToBeUpdated 标记从文档目录到页面对象的对象路径以包含在增量更新中。


如果签名不允许添加注释,但允许编辑表单,即如果有一个认证签名允许填写表单和数字签名,您可以至少填写表格字段。这尤其可能包括将按钮的外观设置为您选择的图像,因为 Adob​​e 经常将按钮误用作伪图像字段。这当然意味着您需要为以后的每个所需添加准备一个字段。

如果签名甚至不允许这样做,即如果有一个认证签名不允许更改,或者如果没有可用于添加的开放表单字段,那么你就退出了运气。

顺便说一句,从 PDF 2.0 开始,认证级别也可以通过在批准签名的签名锁定字典中的条目变得更严格。在上述情况下,您可能需要考虑这一点...

【讨论】:

  • saveIncremental(OutputStream output, Set&lt;COSDictionary&gt; objectsToWrite) 自 2.0.22 起在 2.0 分支中可用,作为问题 issues.apache.org/jira/browse/PDFBOX-45 的一部分,该问题需要 15 年才能解决?
  • 非常感谢@mkl 的答案和代码。这样就解决了问题。 Prio你的答案我尝试了不同的方式,但它没有奏效。但你的代码终于完成了这项工作。
  • @TilmanHausherr 啊,好的。我通常只针对 3.0.0-SNAPSHOT 进行测试,所以我不知道该功能已经包含在 2.x 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2012-02-15
相关资源
最近更新 更多