经过广泛的谷歌搜索,我开始怀疑我是否在某种程度上错过了数字签名的重点。
这基本上是我认为我原则上应该能做到的,我希望iTextSharp能够允许我:
我正在用C#和.NET编写,并使用iTextSharp来解析PDF文件。我有一个未签名的PDF文件,也是同一文件的签名版本。
我知道数字签名从根本上散列了PDF数据,用私钥对其进行加密,然后部分验证过程是使用公钥对其进行解密,并确保在再次进行散列时结果与PDF数据匹配。
除此之外,我想获得这个解密的文档哈希,并将其与我的未签名PDF生成的文档哈希进行比较。这是因为我不仅要验证签名的PDF是否真实,而且还要记录我记录的相同的无签名PDF。我想我也可以通过比较PDF数据(没有签名)和记录的PDF数据来做到这一点。
我目前还没有弄清楚如何做到这一点!即:
- 如何从签名的PDF中提取PDF数据,不包括签名?
- 或者,如何从未签名的PDF生成哈希?
- 与2.一起,如何从PDF签名中提取解密的哈希?
希望这很清楚,我没有错过任何地方的观点!
对这个:
“这是因为我不仅要验证签名的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();
此外,如果服务器收到一个未签名的文件,则返回签名,签名可能只涉及文件的一部分而不是全部。在这种情况下,签名摘要可能不足以识别文件。
从PDF规范(我帐户中的粗体部分):
通过计算数据的摘要来创建签名 (或部分
数据) 在文档中,并将摘要存储在文档中。(...)
有两种定义的技术用于计算可重现的摘要
全部或部分PDF文件的内容:
-一个 字节范围摘要 计算文件中的字节范围,由签名字典中的ByteRange条目指示。这个
range通常是整个文件,包括签名字典
但不包括签名值本身(内容条目)。
- 对象摘要(PDF 1.5)由计算 选择 走路 子树 内存中的对象,从引用的对象开始,
这通常是根对象。由此产生的摘要,以及
有关如何计算的信息放在签名中
参考字典(...)。
验证签名PDF完整性的策略:
不要首先发送未签名的PDF。使用iText(适用于Linux的应用程序的Java版本),签名和 证明 使用的文件 CERTIFIED_FORM_FILLING
。
让最终用户将其签名添加到表单字段并将其发回。这可以做到,因为对表单的更改不会破坏文档认证。
验证签名和文档证书。
您应该能够从iText文档中找出如何完成所有这些操作:
http://itextpdf.sourceforge.net/howtosign.html
您需要做的就是验证认证文档与原始文档是否相同,将文档元数据与原始元数据进行比较。作为潜在的好候选人,脑海中浮现出这个头衔。
要从pdf获取标题以使用iText进行比较,您只需使用以下代码:
PdfReader reader = new PdfReader("AsignedPDF.pdf");
string s = reader.Info["Title"];