PDFBox 多重签名提供无效签名 Java

PDFBox multiple signature giving invalid signature Java

我有一些 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 中显示正常 reader。

请查找link Java源代码和pdf示例以供参考。 Google 开车 link pdf_multi_signs_pdfbox_java

如有任何帮助,我们将不胜感激。

简而言之,您的代码中存在许多问题。导致 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 

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

在当前版本(例如 2020.013.20066)中,Adobe Reader 在两次签名的文件中甚至将第一个签名标记为损坏。在早期版本(例如 2019.012.20040)中,它没有这样做。这可能是Shadow Attacks发布后验证码加固的结果。

顺便说一句:如果您遇到处理签名文档(表格填写、再次签名、...)破坏旧签名的情况,请始终检查原始文档是否可能已经有问题了。检查是否允许对已签名文档应用更改,对错误非常敏感,否则这些错误会在后台修复,因此不可见。

无效的部分字段名称

您使用电子邮件地址作为字段名称,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)

这本身并不是一件坏事,但请注意,如果您对一个已经包含此类条目的先前签名的文件执行此操作,并将它们设置为与以前不同的值,这会使前者无效signature,见issue.

无需设置 PDF 版本

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

document.setVersion(1.0f);

(SignAndIdentifySignatureFields方法addEmptySignField)

document.setVersion(2.0f);

(Sign2方法addEmptySignField)

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

...

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