使用文档哈希将签名的PDF与未签名的PDF进行比较

spl*_*dje 11 c# pdf itextsharp

经过广泛的谷歌搜索,我开始怀疑我是否在某种程度上错过了数字签名的重点.

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

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

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

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

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

  1. 如何从签名的PDF中提取PDF数据,不包括签名?
  2. 或者,如何从未签名的PDF生成哈希?
  3. 与2.一起,如何从PDF签名中提取解密的哈希?

希望这很清楚,我没有错过任何地方的观点!

yms*_*yms 7

对这个:

"这是因为我不仅想验证签名的PDF是否真实,而且还记录了我记录的相同的无签名PDF"

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

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

值得一提的是,有两种类型的PDF签名,批准签名和认证签名.来自Adobe的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();
Run Code Online (Sandbox Code Playgroud)

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

从PDF规范(我帐户中的粗体部分):

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

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

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


Kev*_*ker 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"];
Run Code Online (Sandbox Code Playgroud)