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



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

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

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

有办法检查一下吗?我试过检查字节范围,但签名的pdf的内容似乎完全不同:

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

提前谢谢。

我假设您使用集成的嵌入式签名而不是分离的签名文件对PDF进行签名。你没有明确地这么说,locos2k似乎也有相反的假设,但对于一个独立的签名,你的问题IMO是没有意义的

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

这非常困难,因为PDF签名服务在签名前会对原始PDF进行许多不同的更改,特别是在没有预先签名的情况下。例如,他们可能

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

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

当然,您可以检查特定方面,例如

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

但您可能会忽略一些看似微小的更改,但这些更改可能会显著更改文档的外观。

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

在你的代码中,你会检查你的作者签名的存在性和有效性。如果这些没有问题;仅仅是";必须检查增量更新。

不过,要注意,即使检查这些增量更新是否包含不需要的更改也很困难。在PDF不安全网站上,描述了一些攻击,在它们发布之前,这些攻击可能会愚弄广泛使用的PDF验证器(Adobe Acrobat就是其中之一)的允许/不允许更改的验证例程。

因此,即使简化为增量更新分析,您的任务也绝对不是琐碎的。

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

认证签名

有两种不同的签名:

(1)认证签名(也称为"文档签名"或作者签名")

(2)批准签名(也称为"用户签名")

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

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

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

(a) 更改了您的动态内容(填写表单字段,添加一些注释,…)以提取这些更改和流程以供进一步使用?或者你想知道用户是否

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

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

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

我建议使用Apachescommon-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 
}

最新更新