如何解释 signatureCoversWholeDocument() == false?

How to interpret signatureCoversWholeDocument() == false?

在尝试验证某个 pdf 的签名时,我使用了以下 code

验证结果看起来不错,除了一件事:SignatureUtil#signatureCoversWholeDocument returns false.

很明显这意味着什么。但是我不确定如何解释这个。

如何确定文档的哪些 部分没有被签名覆盖?

一些邪恶的家伙可以更改文档的内容(如果它被发现)同时仍然保留有效签名吗?

换句话说:我如何保证这不是什么值得担心的事情?

你说的很明显是什么意思 SignatureUtil#signatureCoversWholeDocument returns false 但是为了确定,首先是一些背景。

PDF 签名未覆盖整个文档是什么意思

在应用它们的那一刻,PDF 签名覆盖了它们各自的整个文档(当然,除了嵌入的签名容器本身,或者更确切地说,它的占位符可能会更大一些):

签名字节的范围(从文件开始到占位符开始以及从占位符结束之后到文件结束)在 PDF 的签名部分指定。

现在 PDF 格式不仅允许从头开始 re-building 整个文档添加到 PDF 文档,而且还可以在文档结束后以所谓的 增量更新 [=75] 添加更改=].

由于 PDF 签名所签名的字节范围在文档中指定,因此该机制甚至可用于向已签名的 PDF 添加更改,而无需以加密方式破坏签名。

例如,可以使用此机制将多个 PDF 签名应用于一个文档:

但该机制也可用于无数其他类型的更改。

允许和不允许的更改

如果可以在不破坏加密签名的情况下对签名的 PDF 添加任意更改,那么人们可能想知道签名的值是什么。

当然,总是可以提取和 display/process PDF 签名涵盖的 PDF 修订(只需将部分文档从其开始到第二个签名字节范围的结尾)。因此,被签名完全覆盖的原始 PDF 是什么样子一目了然。因此,签名的 PDF 可以被认为是逻辑文档的集合,松散地相互依赖:对于每个签名,它所涵盖的文档加上(如果有其他未签名的添加)完整文档。

实际上在某些用例中这是有意义的,例如由许多作者创建的文档,每个作者都签署了各自编辑的文档版本。

但该视图过于分散的用例数量仍然更多(或至少更重要)。特别是有许多具有多个签名的用例,其中人们希望 PDF 表示由多人签名的 单个 逻辑文档,最多有一些额外的形式 fill-ins第一个签名。

为了支持此类用例,PDF 规范定义了一系列允许的更改。这样的集合可以通过文档的第一个签名来选择。有关这些允许的更改集的详细信息,请参阅 this answer。特别是此类允许的更改可能包括

  • 添加或编辑注释,
  • 提供表单字段值,或
  • 数字签名。

确定 PDF 中的更改并检查它们是否在实践中被允许

根据上一节,OP 的问题归结为如何确定增量更新中更改的性质以及如何确定它们是被允许还是不允许。

确定 PDF 中的哪些 low-level 对象实际上发生了变化并不难确定,请参阅 PdfCompare and PdfRevisionCompare classes in

真正的问题是检查 low-level 对象中的这些更改是否可以被视为仅服务于指定的允许更改(或者根本不在语义上更改文档)!

这里即使是“黄金标准”(即 Adob​​e Acrobat)也会一次又一次地犯错,都未能识别不允许的更改(参见 "Attacks on PDF Certification" on pdf-insecurity.org for examples that meanwhile have been fixed) and in failing to recognize allowed changes (see e.g. and here)。

本质上这是一个非常困难的任务。而且你不太可能在某个开源项目中找到一个好的实现。

特别是 iText 7 不包括这样的分析。因此,如果你想要它,你必须自己实现它。

如果您希望特定软件应用更改,则可以稍微简化任务。在这种情况下,您可以分析软件如何(根据 low-level 对象)应用允许的更改并仅接受此类 low-level 更改。例如,Adobe Acrobat 非常擅长识别 Adob​​e 软件对 Adob​​e 软件创建的 PDF 应用的允许更改。