PDF/A-3A 文档的 PAdES LTV 签名产生无效签名

PAdES LTV signing of a PDF/A-3A document yields invalid signature

简介

我对标记为 PDF/A - 3A 兼容的 PDF 文档进行数字签名时遇到问题。使用 PDFBox(最新版本,2.0.24)我最终在 Adob​​e Acrobat 中得到一个无效签名,而使用 iText7(最新版本)我得到一个有效签名。目标是获得符合 PAdES LTV 的签名。

概览

我的过程如下(同时使用 PDFBox 和 iText7):

对于PDFBox,签名代码是here and for OCSP/CRL embedding is here。 对于 iText7,用于签名和 OCSP/CRL 嵌入的代码是 here.

问题

现在,这适用于大多数 PDF 文件,包括多重签名文档。问题出在一个特定的 PDF 上,该 PDF 创建为 PDF/A compliat,级别 3A。

使用 PDFBox,如果我只是嵌入签名并在 Adob​​e Acrobet 中打开文档,签名是有效的。如果我还嵌入 OCSP/CRL 内容,签名将不再有效。 Adobe Acrobat 抱怨:

Signature is invalid: Document has been altered or corrupted since it was signed.

我也注意到,只要这样做:

document.load(inputStream);
document.save(outputStream);

我把签名弄坏了。根据我的测试,实际嵌入并不是问题的真正原因,而只是我在嵌入签名后重新打开 PDF 并将其保存回磁盘这一事实。

通过 iText7 使用相同的过程(密钥、证书等),我最终在 Adob​​e Acrobat 中获得了有效的 LTV 签名。

示例 PDF

示例文档是 here。原件包含未签名的文档,然后有2个示例,一个用于PDFBox(在Adobe Acrobat中无效)和一个用于iText7(在Adobe Acrobat中有效)。

到目前为止,我的研究表明 PDFBox 在签名嵌入后加载 PDF 时以某种方式破坏了元素的顺序。它提示 加载和保存文档,但对于所有其他 PDF,我执行相同的过程并且 Adob​​e Acrobat 不会抱怨签名。

我也尝试使用 PDFBox 2.1.0-SNAPSHOT 和 3.0.0-SNAPSHOT,希望这个问题与 PDF 中元素的排序有关并且已得到修复。尽管如此,我还是得到了相同的结果。

稍后编辑 1

请看下面的后期编辑2,这里的后期编辑1不是个好主意!

根据下面@mkl 接受的答案,问题出在原始 PDF 文件上,其中包含交叉引用 table 分成几个小节而不是一个小节。这似乎是由首先生成 PDF 的服务使用的库(Aspose PDF for .NET,版本 21.3 或更早版本)引起的。

似乎适用于我当前代码的一种解决方法如下:

PDDocumentInformation info = pdDocument.getDocumentInformation();
if (info != null && StringUtils.containsIgnoreCase(info.getProducer(), "Aspose")) {
try {
    pdDocument.save(inMemoryStream);
    pdDocument.close();
    pdDocument = PDDocument.load(inMemoryStream.toByteArray());
    inMemoryStream.reset();
} catch (Exception e) {

基本上,如果我检测到文档的制作者是 Aspose,我会将文档保存在内存中(通过 PDFBox' pdDocument.save())并加载回来.这确保交叉引用 table 被正确写入内存,并且从那里签名和 OCSP+CRL 嵌入按预期工作,在 Adob​​e Acrobat 中产生有效签名。

稍后编辑 2

谢谢@mkl 和@TilmanHausherr,你是对的。假设某个库生成的所有文档都必须自动规范化不是一个好主意,因为现有签名将失效。最后,更好的想法是保持代码原样,并期待一个正确构造的 PDF。修复创建位置问题

该问题是由于原始PDF中的错误引起的。您的 PDFBox 代码以附加模式(即增量更新)签名,因此签名版本中也存在该错误。您的 iText 代码不会以附加模式登录,而是重写整个 PDF;在这样做的同时,它不会出现与原始 PDF 制作者相同的错误,因此错误不再出现在签名版本中。 Adobe Acrobat 在使用更新验证签名时对此类问题非常敏感。

错误

PDF 中初始修订版的交叉引用 table 不得拆分为单独的小节,但如果是原始 PDF,则它已被拆分:

0 75
0000000000 65535 f
0000000018 00000 n
...
0000313374 00000 n
0000313397 00000 n
76 20
0000313419 00000 n
0000313443 00000 n
...
0000846048 00000 n
0000846175 00000 n

类似案例已在 , , 和其他地方讨论过;您还可以在这些答案中找到一些规范参考。

通常这不会引起注意,Adobe Acrobat 在 PDF 中遇到小问题时通常很松懈。

通常,也就是说,除了在签名修订后验证具有集成签名和增量更新的文档时,在那种情况下,Adobe Acrobat 经常认为此类问题可疑并且无法验证签名,即使在签名修订后没有增量更新的情况下验证相同的 PDF 时它不会抱怨。

您处于那种危急情况,您的最终文档包含签名修订后的增量更新,更新包含验证相关信息。

谁造成了错误?

根据原始 PDF 的 Info 字典,它是由“Aspose.PDF for .NET 21.3.0”生成的。已知 Aspose.PDF 的早期版本会创建此类错误的交叉引用 table(请参阅 的“损坏 PDF 的 PDF 处理器”部分)。显然 Aspose 还没有解决这个问题。