【问题标题】:PDFBox multiple signature giving invalid signature JavaPDFBox多重签名给出无效签名Java
【发布时间】:2020-11-26 10:47:21
【问题描述】:

我有一些 pdf 多签名工作流程要求。在此 pdf 中,将多次签署而不更改文件,例如 2 人或更多人可以签署同一份文件。 我试图在 pdf 中添加签名两次,但在第二次签署 pdf 后,第一个签名无效。我已经使用 PDFBox Java api 来创建 pdf 签名。

PDF 创建步骤:

  1. 通过添加空签名字段名称创建 pdf:suhasb@gmail.com 和 nikhil.courser@gmail.com 使用原始 hello.pdf 输出文件名 hello_tag.pdf 运行程序 >TagPDFSignatureFields.java
  2. 第一次通过从 hello_tag.pdf 文件中获取签名字段 suhasb@gmail.com 进行签名,输出文件名为 hello_signed.pdf 运行程序 >SignAndIdentifySignatureFields.java
  3. 通过从hello_signed.pdf文件中获取签名字段nikhil.courser@gmail.com进行第二次签名,输出文件名为hello_singed2.pdf 运行程序>Sign2.java

在第 2 步中,pdf 得到正确签名,但在第 3 步之后,第 2 步签名版本无效,第 3 步签名在 acrobat 阅读器中显示正常。

请查找链接 Java 源代码和 pdf 示例以供参考。 谷歌驱动链接pdf_multi_signs_pdfbox_java

任何帮助将不胜感激。

【问题讨论】:

  • 第一个错误:您在签名字段部分名称中使用句点字符 ('.')。这是无效的,部分名称不能包含句点字符。
  • @mkl 我刚刚遇到了相反的问题 - 我们通过代码填充的 PDF(Companies House 的 CS01 表格,公司在英国注册)包含带有句点的部分名称.我们现在通过恢复版本来修复它,但我想这也可能对其他人造成破坏。
  • 部分名称中的句点无效。您应该通知 Companies House 他们正在发布损坏的表格。

标签: pdf pdfbox digital-signature signature


【解决方案1】:

简而言之,您的代码中存在许多问题。添加第二个签名后导致 Adob​​e Reader 将您的第一个签名标记为无效的问题实际上已经在您的准备步骤TagPDFSignatureFields 中,您在其中创建了无效的重复页面树条目。其他问题也应该得到修复,尽管 Adob​​e Reader 目前没有抱怨。

详细问题...

重复的页面条目

TagPDFSignatureFields 你的方法addEmptySignField 是这样开始的:

private void addEmptySignField(String[] args) throws Exception, IOException {
    // Create a new document with an empty page.
    try (PDDocument document = PDDocument.load(new File(args[0]));)
    {
        PDPage page = document.getPage(0);
        document.addPage(page);

在这里您检索document 的第一页并立即将该页再次添加到document。这会导致文件 hello_tag.pdf 中的页面根树节点如下所示:

2 0 obj
<<
/Type /Pages
/Count 2
/Kids [6 0 R 6 0 R]
>>
endobj 

即页面树包含两次 Adob​​e Reader 不接受但在后台修复的相同页面对象。对于已签名的文档,Adobe Reader 会以模糊的方式警告这一点:

在当前版本(例如 2020.013.20066)中,两次签名文件中的 Adob​​e Reader 甚至将第一个签名标记为损坏。在早期版本(例如 2019.012.20040)中,它没有这样做。这可能是影子攻击发布后验证代码强化的影响。

顺便说一句:如果您在处理已签名文档(表格填写、再次签名等)时会破坏旧签名,请务必检查原始文档是否可能已经存在问题.检查是否允许对已签名文档进行更改,对错误非常敏感,否则这些错误会在后台修复,因此不可见。

部分字段名称无效

在您的示例中,您使用电子邮件地址作为字段名称,suhasd@gmail.comnikhil.courser@gmail.com

signatureField.setPartialName("suhasd@gmail.com");
...
signatureField1.setPartialName("nikhil.courser@gmail.com");

(TagPDFSignatureFields 方法addEmptySignField)

这些部分字段名称无效,部分字段名称不得包含句点字符('.')。

未来版本的 PDFBox 将尝试防止这种情况发生,请参阅PDFBOX-5028

在签名时设置默认资源和默认外观

在签名期间,您设置 AcroForm 字典的默认资源和默认外观:

acroForm.setDefaultResources(resources);
...
acroForm.setDefaultAppearance(defaultAppearanceString);

SignAndIdentifySignatureFieldsSign2 方法 addEmptySignField

这本身并不是一件坏事,但要注意,如果您对已具有此类条目的先前签名的文件执行此操作,并且您将它们设置为与以前不同的值,这可能会使以前的签名无效,见问题answered here

无需设置PDF版本

您尝试更改文档声明的 PDF 版本:

document.setVersion(1.0f);

(SignAndIdentifySignatureFields 方法addEmptySignField)

document.setVersion(2.0f);

(Sign2 方法addEmptySignField)

第一条指令被忽略,因为文档本身已经需要至少 1.5 的版本,但第二条指令确实将文档 PDF 版本设置为 2.0,这可能会导致老观众出现问题。

...

很可能还有更多问题。我只是第一次发现这些问题,然后才意识到已经修复了唯一的第一个问题,即重复页面条目,足以修复第一个签名......

【讨论】:

  • 感谢@mkl 删除了重复的条目,它现在可以工作了。
  • 更正无效的部分字段名称
  • 删除了在签名时设置默认资源和默认外观
  • 删除设置 PDF 版本
  • Pdf 最初是 Adob​​e 定义的格式,但在 2008 年他们将其交给 ISO 以使其成为国际标准。那年它作为 ISO 32000-1 发布。 2017 年更新发布为 ISO 32000-2。 ISO 标准通常必须购买,它们不是免费的,但在这种情况下,Adobe 发布了一份没有 ISO 标头的 ISO 32000-1 副本供免费下载,只有谷歌的 pdf32000。
猜你喜欢
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 2016-01-20
相关资源
最近更新 更多