如何检测签名的pdf对iText有效?

时间:2016-12-05 16:45:33

标签: java pdf itext digital-signature

对于项目,我需要检查数字签名是否有效。 我已经开发了一段代码来完成它。 我测试了一些pdf(正确与否),代码似乎工作。 但有一种情况是验证不起作用。

在Adobe Reader中我发现了消息"文档自签名以来已被更改或损坏。"与#34;美丽"红十字... 不幸的是,我不知道如何测试这个最重要的案例。

因为如果我理解,签名是正确的,但它是被更改的文件,而不是签名。

我想我们可以使用文件的哈希值,但我不知道如何正确提取这些信息。

如何使用Itext检查?

有关信息,我测试了以下方法:

  • pdfpkcs7.verify():return true
  • acroFields.signatureCoversWholeDocument(signame):return true
  • pdfReader.isRebuilt():return false

2 个答案:

答案 0 :(得分:1)

Adob​​e已在this document中记录了他们在签名中接受的算法选择。特别是它们适用于所有适用的PDF版本

  

DSA仅支持SHA1和adbe.pkcs7.detached

另一方面,OP的文档使用DSA和SHA256。效果是

  • Adob​​e Reader无法正确验证哈希值,但
  • iText(不限于那些算法组合)可以。

实际上签名本身的签名算法信息一开始是有问题的,它只使用OID 1.2.840.10040.4.1,它只表示使用了DSA,而不是它使用的摘要算法。严格来说,应该使用不同的OID:

  • for SHA1withDSA:1.2.840.10040.4.3
  • for SHA256withDSA:2.16.840.1.101.3.4.3.2

(甚至还有一些替代方案,其中大多数都被弃用了。)

仅查找1.2.840.10040.4.1(仅DSA)验证器必须猜测/推断摘要,并假设SHA1(如Adobe Reader)不完全不合理。

iText最有可能猜测使用过的SHA256,因为此摘要算法还用于计算签名属性messageDigest中的文档摘要。

答案 1 :(得分:0)

iText:使用 iText 避免 PDF 数字签名漏洞。 links

<块引用>

2019 年 2 月,来自德国波鸿鲁尔大学的一组安全研究人员公布了许多 PDF 查看器和在线 PDF 数字签名服务的数字签名系统中的漏洞详细信息。在对这些漏洞进行调查后,我们发现 7.1.5 版本中引入的 iText 最近更新意味着我们不易受到所描述的攻击。<​​/p> <块引用>

但是,已确定可以改进用于检查和验证签名的方法的当前名称,以更好地反映其功能。因此,我们决定弃用 SignatureUtil#verifySignature 和 PdfPKCS7#verify 方法,并用 iText 7.1.6 中引入的 SignatureUtil#readSignatureData 和 PdfPKCS7#verifySignatureIntegrityAndAuthenticity 替换它们。

以下代码示例展示了如何对每个 iText 版本使用签名完整性和真实性检查。 iText 7.1.6:

PdfDocument pdfDocument = new PdfDocument(new PdfReader(input));
 
// Checks that signature is genuine and the document was not modified.
boolean genuineAndWasNotModified = false;
 
String signatureFieldName = "Signature1";
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
try {
    PdfPKCS7 signature1 = signatureUtil.readSignatureData(signatureFieldName);
    if (signature1 != null) {
        genuineAndWasNotModified = signature1.verifySignatureIntegrityAndAuthenticity();
    }
} catch (Exception ignored) {
    // ignoring exceptions,
    // we are only interested in signatures that are passing the check successfully
}
 
pdfDocument.close();
<块引用>

第二种和第三种类型的攻击,增量保存攻击 (ISA) 和签名包装 (SWA),基于尝试将一些恶意数据插入 PDF 文件以覆盖签名数据。

<块引用>

为了验证每个签名,有必要检查它是否覆盖了整个文件,否则 iText 无法确定有问题的签名确实签署了构成当前 PdfDocument 及其所有内容的数据。即使签名真实且签名数据完整性完好,iText 也会始终检查签名数据是否不仅是 PDF 内容的一部分,而且还是有效的 PDF 文件。

<块引用>

iText 在 SignatureUtil.signatureCoversWholeDocument(String fieldName) 方法中实现此检查。对于 ISA 和 SWA 攻击,此方法将返回 false,因为文件中插入了一些未签名的数据:

<块引用>

实际上,我们在 2018 年 11 月(在我们意识到报告的漏洞之前)通过重写 signatureCoversWholeDocument() 方法解决了这个特定问题。如果您使用 iText 7.1.5(或更高版本),以下代码应正确验证 PDF:

PdfDocument pdfDocument = new PdfDocument(new PdfReader(input));
 
String signatureFieldName = "Signature1";
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
 
Boolean completeDocumentIsSigned = signatureUtil.signatureCoversWholeDocument(signatureFieldName)}
if (!completeDocumentIsSigned) 
{
    // handle PDF file which contains NOT signed data
}
 
pdfDocument.close();

注意:未涵盖整个文档的签名不能视为验证 PDF 文件,因为签名未涵盖的内容可能在创建签名后已被修改。