12

在广泛的谷歌搜索之后,我开始怀疑我是否以某种方式错过了数字签名的意义。

这基本上是我认为我原则上应该能够做到的,我希望 iTextSharp 将允许我:

我正在用 C# 和 .NET 编写并使用 iTextSharp 解析 PDF 文件。我有一个未签名的 PDF 文件,以及同一文件的签名版本。

我知道数字签名从根本上对 PDF 数据进行散列,用私钥对其进行加密,然后验证过程的一部分是使用公钥对其进行解密,并确保在再次散列时结果与 PDF 数据匹配。

除此之外,我想获得这个解密的文档哈希,并将其与我的未签名 PDF 生成的文档哈希进行比较。这是因为我不仅要验证签名的 PDF 是否真实,还要验证它是否与我记录在案的未签名 PDF 相同。我想我也可以通过将 PDF 数据(没有签名)与我记录的 PDF 数据进行比较来做到这一点。

我目前还没有弄清楚如何做到这一点!IE:

  1. 如何从已签名的 PDF 中提取除签名之外的 PDF 数据?
  2. 或者,如何从未签名的 PDF 生成哈希?
  3. 除了 2.,如何从 PDF 签名中提取解密的哈希?

希望这很清楚,我没有在某个地方错过重点!

4

2 回答 2

7

对这个:

“这是因为我不仅要验证签名的 PDF 是否真实,还要验证它是否与我记录在案的未签名 PDF 相同”

假设您只想知道您在服务器上获得的文档是真实的:

创建签名文档时,您可以选择仅签名文件的一部分或整个文档。然后,您可以使用“整个文档”签名,如果您返回到服务器上的文档是“真实的”(这意味着签名验证成功),那么它肯定是您记录在案的同一文档。

值得一提的是,PDF 签名有两种类型,批准签名和认证签名。来自 Adob​​e 的 PDF 中的数字签名文档:

(...) 批准签名,即某人签署文件以表示同意、批准或接受。经认证的文档是在文档可供使用时具有由发起人应用的认证签名的文档。发起者指定允许哪些更改;选择允许的三个修改级别之一:

  • 没有变化
  • 只填写表格
  • 表格填写和评论

假设您想要匹配您在服务器上获得的某些签名文档,以及数据库上的未签名文档:

对于文件识别,我建议单独处理。一旦可以打开一个文档,就可以从其所有页面的解压缩内容的串联中创建一个哈希(例如 md5),然后将其与来自原始文档的另一个类似的哈希进行比较,(可以生成一次并存储在数据库中)。

我这样做的原因是它将独立于文档上使用的签名类型。即使在 PDF 文件中编辑表单域、添加注释或创建新签名,页面内容也不会被修改,它始终保持不变。

如果您使用的是 iText,您可以使用PdfReader.getPageContent方法获取页面内容的字节数组,并将结果用于计算 MD5 哈希

Java 中的代码可能如下所示:

PdfReader reader = new PdfReader("myfile.pdf");
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
int pageCount = reader.getNumberOfPages(); 
for(int i=1;i <= pageCount; i++)
{
     byte[] buf = reader.getPageContent(i);
     messageDigest.update(buf, 0, buf.length);
}
byte[] hash = messageDigest.digest();

此外,如果服务器接收到一个未签名的文件又回来了签名,则签名可能只涉及文件的一部分而不是全部。在这种情况下,签名摘要可能不足以识别文件。

来自 PDF 规范(我帐户上的粗体部分):

签名是通过计算文档中的数据(或部分数据)的摘要并将摘要存储在文档中来创建的。(...)有两种定义的技术可以计算所有或部分内容的可重现摘要PDF 文件的一部分:

-字节范围摘要是在文件中的字节范围内计算的,由签名字典中的 ByteRange 条目指示。此范围通常是整个文件,包括签名字典但不包括签名值本身(内容条目)。

- 对象摘要 (PDF 1.5) 是通过有选择地遍历内存中对象的子树来计算的,从引用的对象开始,该对象通常是根对象。生成的摘要以及有关其计算方式的信息被放置在签名参考字典 (...) 中。

于 2012-10-18T15:03:49.357 回答
5

验证签名 PDF 完整性的策略:

  1. 首先不要发送未签名的 PDF。使用 iText(适用于 linux 友好应用程序的 Java 版本)使用CERTIFIED_FORM_FILLING.

  2. 让最终用户将其签名添加到表单字段并将其发回。可以这样做,因为对表格的更改不会破坏文件认证。

  3. 验证签名和文件证明。

您应该能够从 iText 文档中弄清楚如何执行所有这些操作:http: //itextpdf.sourceforge.net/howtosign.html

要验证经过认证的文档是否与原件相同,您需要做的就是将文档元数据与原件进行比较。这个标题是一个潜在的好候选人。

要从 pdf 中获取标题以使用 iText 进行比较,您只需使用以下代码:

PdfReader reader = new PdfReader("AsignedPDF.pdf");
string s = reader.Info["Title"];
于 2012-10-16T15:20:56.507 回答