3

我正在使用pdftk并进行一些测试,发现将多页 PDF 文件分解为单独的单页 PDF 文件,然后为每个单页 PDF 生成一个 md5 哈希校验和(数字指纹),每次我都会产生不同的哈希做爆发。这就是结果,即使它是完全相同的文件而没有任何更改。

我的测试过程是:

  1. 解压 test.pdf(包含 10 页的简单纯文本 PDF)
  2. 使用 pdftk,将 test.pdf 爆裂(拆分)成 10 个单独的 PDF 文件(每个文件 1 页)
  3. 为 10 个单页 PDF 文件中的每一个生成 md5 哈希校验和
  4. 记录 10 个哈希校验和
  5. 重复步骤 1-4
  6. 请注意,所有哈希值都不同

旁注:解压缩后在 PDF 上生成校验和会在重复时产生完全相同的校验和。

我在这个练习中使用了node.js及其加密模块。

我的问题是:为什么校验和在重复时会有所不同?我认为生成的 10 个单页文件与上次创建它们时完全相同。他们的父文档(以及各个页面本身)根本没有改变。

4

2 回答 2

4

根据 PDF 规范,每当 PDF 创建者写出修改后的 PDF 时,它应该更新元数据条目数组中命名/ModDate的键。/Info

此外,它(可能)会将 PDF 的 XMP 元数据结构中的文档 UUID 更改为新 ID。


因此,当您想使用 MD5(或任何类似方法)检查​​ PDF 生成过程中的“稳定结果”(考虑单元测试或其他)时,您应该在应用 MD5 求和之前执行以下两件事之一:

  • 要么“规范化”您的 PDF 输出以始终将相同的 ModDate 和 UUID 写入文件(如果您的 PDF 生成工具允许您以这种方式进行调整),
  • 或对文件运行编辑(您可以使用sed)来规范化文件的/ModDate(并且可能还有/CreationDate)和 UUID 条目。

更新:由于您似乎pdftk已经熟悉,您应该能够转储元数据文本文件(如 Ezra 所示):

pdftk in.pdf dump_data output data.txt

或(如果您需要):

pdftk in.pdf dump_data_utf8 output data.utf8.txt

然后编辑 data*.txt 文件以使其适合您的需求:将 PDF UUID(pdftk调用它们PdfID0/ PdfID1)更改为易于识别的值(00000...fffff...),将日期更改为另一个易于识别的日期。然后使用这些元数据值更新您的文件:

pdftk in.pdf update_info data.txt output in-updated.pdf \
      &&  mv in-updated.pdf in.pdf

或者

pdftk in.pdf update_info data.utf8.txt output in-updated.utf8.pdf \
      &&  mv in-updated.utf8.pdf in.pdf 

然后才运行您的 Md5 校验和,看看它是否有效(或需要更多微调)。

于 2012-07-10T17:13:29.933 回答
2

glib 的答案是校验和,因为数据不同。

我证实了这一点的实验:

首先,我爆破一个pdf并移动文件:

$pdftk Michael-Jordan-I-Cant-Accept-Not-Trying.pdf burst
$md5sum pg_0001.pdf 
150ef33eec73cd13c957194ebead0e93  pg_0001.pdf
$mv pg_0001.pdf 150ef33eec73cd13c957194ebead0e93

接下来,我再次爆破相同的 pdf,再次移动文件:

$pdftk Michael-Jordan-I-Cant-Accept-Not-Trying.pdf burst
$md5sum pg_0001.pdf
49c7c885bc516856f4316452029e0626  pg_0001.pdf
$mv pg_0001.pdf 49c7c885bc516856f4316452029e0626

这证实了您的发现;总和是不同的。经检查,字节 91411-92163 有所不同。

我的直觉告诉我这是日期元数据,因此我确认了这一点:

$pdftk 150ef33eec73cd13c957194ebead0e93 dump_data output 150.txt
$pdftk 49c7c885bc516856f4316452029e0626 dump_data output 49c.txt
$diff -u 150.txt 49c.txt 
--- 150.txt 2012-07-10 11:08:02.371119999 -0600
+++ 49c.txt 2012-07-10 11:08:18.891201910 -0600
@@ -3,9 +3,9 @@
 InfoKey: Producer
 InfoValue: itext-paulo-155 (itextpdf.sf.net-lowagie.com)
 InfoKey: ModDate
-InfoValue: D:20120710105934-06'00'
+InfoValue: D:20120710110010-06'00'
 InfoKey: CreationDate
-InfoValue: D:20120710105934-06'00'
-PdfID0: 51671a1a6c4f5e6bb81b88fc7efd14d0
-PdfID1: 82fd646061863972216ccf8a32cf3c7b
+InfoValue: D:20120710110010-06'00'
+PdfID0: 844f34f87275b9184ebe10b82d3397c9
+PdfID1: 8f555a30216e37d77abaf03a4217b2a
 NumberOfPages: 1

我不确定你的问题是什么,但如果你真的需要匹配总和,两种明显的方法是:

  1. 将日期设置为相同。
  2. 仅使用前 N 个字节来计算总和;省略有问题的元数据。
于 2012-07-10T17:15:05.967 回答