如何在应用签名之前检查PDF是否已被修改 - pdfbox

How to check if PDF has been modified before applying signature - pdfbox

我有一个简单的网络应用程序,允许用户下载包含一些动态信息的 pdf。

然后用户应该签署文档并使用我的应用程序重新上传它。

现在,我需要在签名前检查用户是否更改了PDF内容。

有没有办法检查这个?我试过检查 byteRange,但签名的 pdf 的内容似乎完全不同:

Original file size: 2280
Signed file size: 31485
Byte range: [0, 11433, 29635, 1850]

提前致谢。

最简单的方法是在将文件发送给用户之前存储文件的哈希值,然后在用户提交文件时再次对文件进行哈希处理。如果哈希值不同,则文件已被修改。

我建议使用 Apaches common-codec 来执行此操作:

public String getSha1Hash(Path file) throws IOException {
   try(InputStream is = Files.newInputStream(file)) {
      return DigestUtils.sha1Hex(is);
   }
}

然后在您将 pdf 发送给您的函数中,您可以执行以下操作:

Path pdf = pdfPath; //the path to the pdf file
String outgoingHash = getSha1Hash(pdf);
store(pdf, outgoingHash) //store the pdf filename and its hash in a db or some other way

当用户提交 pdf 时,您将执行以下操作:

Path pdf = pdfPath; //path to the incoming file. This might be a stream so adjust for that
String incomingHash = getSha1Hash(pdf);
String originalHash = getFileHash(pdf);

if (incomingHash.equals(originalHash)) {
   //handle same hash value (file wasnt modifieD)
} else {
   //handle changed file 
}

我假设您使用 集成的嵌入式签名 签署 PDF,而不是分离的签名文件。您没有明确这么说,locus2k 似乎另有假设,但是对于分离的签名,您的问题 IMO 没有意义。

Now, I need to check wheter the user has changed the PDF content before signing it.

这非常困难,因为 PDF 签名服务在签名前对原始 PDF 应用了许多不同的更改,尤其是在没有事先签名的情况下。例如。他们可能

  • 线性化文件(这意味着按特定顺序对 PDF 文件中的对象进行排序),
  • 修复其中的小错误,
  • 优化部分结构,
  • 为没有的表单字段创建外观,
  • ...

因此,必须检查您确定的所有差异,它们可能是签名过程的一部分,而不是用户先前操作的一部分。

当然你可以检查具体的方面,例如

  • 从原始文件和签名副本中提取文本并进行比较,
  • 渲染原始文件和签名副本并进行比较(仅允许在预定义的签名区域存在差异),
  • ...

但您可能会通过这种方式忽略看似微小的更改,但这些更改会显着改变文档的外观。

有一些方法可以使工作更轻松,例如您可以先使用作者签名签署您的原始 PDF,您可以在其中声明您允许对文档进行哪些更改。这应该至少使用户难以在签名前使用未经操纵的标准软件进行不允许的更改。此外,这将签名软件的更改限制为增量更新,从而阻止了完整的 PDF 大修。

在您的代码中,您将检查您是否存在该作者签名及其有效性。如果这些都没有问题,您“只需”检查增量更新即可。

但是请注意,即使检查这些增量更新是否包含不需要的更改也很困难。在 PDF Insecurity 网站上描述了许多攻击,在它们发布之前,这些攻击可能会愚弄 allowed/disallowed 更改广泛使用的 PDF 验证器(其中包括 Adob​​e Acrobat)的验证例程。

因此,您的任务肯定是 non-trivial,即使减少到增量更新分析。

有一种主要机制可以做到这一点(MKL 部分提到了这一点):

认证签名

有两种不同的签名:

(1)认证签名(也称'document signature'或作者'signature')

(2) 批准签名(也称为'user signature')

基本上,您作为文档作者使用认证签名签署文档。此签名与其他签名略有不同。 (例如它的坐标为0 0 0 0,必须是文档中的第一个签名...)应用认证签名有以下优点:

  • 作者可以指定用户可以做什么,不可以做什么
  • 用户还可以在收到文档时验证文档没有被更改(有意或无意)
  • 所有更改必须在增量更新模式下完成,否则用户将破坏认证签名。

因此,如果您应用了一个认证签名并且用户将他的更改添加为增量更新,那么您可以检查增量更新以查看更改的内容。正如 MKL 所指出的,这并不总是微不足道的,在我看来取决于您的用例: 是不是想知道一个用户是否

(a) 更改了您的动态内容(填写的表单域、添加了一些评论、...)以提取这些更改和处理以供进一步使用?或者您想知道用户

(b) 确实操纵了 PDF,更改了一些文本,添加了图像等,所以您想检测欺诈性更改?

两者皆有可能,但复杂程度各不相同。很容易提取更改的表单数据或注释内容。其他变化更难以提取和检测。但这也可能取决于您使用的工具。有些人可能会为此提供比其他人更多的支持...