使用iText从PCKS7签名的PDF文件中获取哈希/摘要

时间:2015-04-29 09:38:34

标签: java pdf itext pkcs#7

我正在编写一个Java Web服务,它使用iText从网络中的某些客户端签署PDF文档。文档正确签名,可以使用外部工具进行验证。但是,由于为了将此文档存储在官方文档库中而存在一些法律限制,我必须提供签名中的哈希/摘要消息。

我已经尝试了几乎任何东西来获取该哈希值,但我能得到的最接近的是使用此代码片段获取整个签名(CERT + HASH / DIGEST + TIMESTAMP)作为字符串(原谅字符串和[1] ]因为我只是测试如何做到这一点):

    PdfReader reader = new PdfReader(path);
    File temp = TempFileManager.createTempFile("aasd2sd", "asdasda222cff");
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(temp));
    stamper.setRotateContents(false);
    PdfString firma = (PdfString) stamper.getAcroFields().getSignatureDictionary("Signature1").get((PdfName)stamper.getAcroFields().getSignatureDictionary("Signature1").getKeys().toArray()[1]);

据我所知,我得到了一个DER-enconded PKCS7签名。但是,我不知道如何解读/读取这些信息以便达到目的。

有什么想法吗?

谢谢, 克里斯。

1 个答案:

答案 0 :(得分:4)

首先,在PKCS#7 / CMS签名的情况下,签名中不一定有 哈希/摘要消息通常涉及多个哈希,参见this answer to Message digest of pdf in digital signature

考虑到您需要摘要来实现某些法律限制,我假设您已经使用了签名属性MessageDigest的值(如果存在) ETSI.CAdES.detached adbe.pkcs7.detached 类型PDF签名是签名字节范围的摘要。

如果你想使用iText类(即不是安全提供程序类)这样做,你必须克服一个小问题,即你所追求的值存储在一个私有成员中{{1 }})。但是,有些反射允许您访问它:

PdfPKCS7.digestAttr

您可以在更完整的示例ExtractHash.java中找到用于输出PDF文档中签名字段的gigest算法和摘要值的方法,例如:

void extractHashes(PdfReader reader) throws Exception
{
    AcroFields acroFields = reader.getAcroFields();
    List<String> names = acroFields.getSignatureNames();

    for (String name: names)
    {
        PdfPKCS7 pdfPkcs7 = acroFields.verifySignature(name);
        pdfPkcs7.verify();

        Field digestAttrField = PdfPKCS7.class.getDeclaredField("digestAttr");
        digestAttrField.setAccessible(true);
        byte[] digestAttr = (byte[]) digestAttrField.get(pdfPkcs7);

        // process the digest value in digestAttr 
    }
}