1

我正在尝试获取已签名 PDF 的原始文档,以便将其哈希值与存储的文档进行比较。

当文档有多个签名时,这真的很容易,使用 acrobat reader 你可以去文档的上一个版本保存它,就是这样。

令人惊讶的是,这不适用于第一个签名,因为没有直接的方法来获取原始数据。

因为我用 iTextSharp 以编程方式尝试过的阅读器无法做到这一点。但是,尽管我已经深入搜索,但我还没有找到如何做到这一点。我发现的唯一相关帖子是这个但没有提供解决方案。

有没有人遇到过这个问题并找到了解决方案?

提前致谢。

编辑:我把根据 mkl 的响应提取数据的代码放在这里。阅读回复的评论,以提防未签名 PDF 长度不固定的问题。

String sOriginalText = File.ReadAllText("FileSigned.pdf", Encoding.Default);
int sTrailerNumberPosition = sOriginalText.LastIndexOf("]/Prev ") + "]/Prev ".Length;
int sTrailerNumberEndPosition = sOriginalText.IndexOf(">", sTrailerNumberPosition);
String sTrailerIndex = sOriginalText.Substring(sTrailerNumberPosition, sTrailerNumberEndPosition -sTrailerNumberPosition);
int iTrailerIndexPosition = sOriginalText.IndexOf(sTrailerIndex + "\r\n%%EOF");
int iEndPosition = sOriginalText.IndexOf("%%EOF", iTrailerIndexPosition) + "%%EOF".Length;
String sOutText = sOriginalText.Substring(0, iEndPosition);
File.WriteAllText("c:/OriginalFile.pdf", sOutText, Encoding.Default);
4

1 回答 1

4

获取已签名 PDF 的原始文档的任务是否完全可以实现,取决于最初应用签名的方式。

  1. 如果签名以附加模式应用(即根据 PDF 规范ISO 32000-1:2008的语言作为增量更新,参见第 7.5.6 节),您只需切断这个附加的增量更新修订。

    由于您有一个存储的文档,可能在签名后已成为您检查的文档,您可以简单地以存储文件的长度剪切签名文件并进行比较,例如使用哈希。这足以表明签名的文档来自您的原始文档。但是,可能还有其他中间修订,因为您可能只是切断了多个增量更新。

    通常,您可以通过将已签名 PDF 的/Prev预告片条目跟踪到先前修订的交叉引用表并从那里移动到文档结束标记%%EOF来找到先前的修订,因为在增量更新中

    添加的预告片应包含除前一个预告片中的 Prev 条目(如果存在)之外的所有条目,无论是否修改。此外,添加的尾部字典应包含一个 Prev 条目,给出前一个交叉引用部分的位置(参见表 15)。每个预告片应由其自己的文件结束 (%%EOF) 标记终止。

    如果 PDF 使用交叉引用流而不是交叉引用表,则交叉引用流字典中有类似的条目:

    (仅在文件具有多个交叉引用流时出现;在混合引用文件中没有意义;参见 7.5.8.4,“与不支持压缩引用流的应用程序的兼容性”)解码流中的字节偏移量文件的开头到前一个交叉引用流的开头。该条目与预告片字典中的 Prev 条目具有相同的功能(表 15)。

    但是,您应该知道,附加的增量更新修订版可以包含除签名之外的其他更改。因此,即使先前的修订与您存储的文档相对应,您仍然只知道签名的文档是基于您保存的文档。

  2. 如果签名附加模式下应用,那么您就很不走运了:处理 PDF 的程序(例如用于签名)可能会完全重新排列文档的二进制内容,甚至可能重新编号对象、更改压缩、删除未使用的对象等,而文档的外观保持不变。

于 2013-04-09T12:29:32.170 回答