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

cri*_*ore 1 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]);
Run Code Online (Sandbox Code Playgroud)

据我所知,我得到了一个 DER 编码的 PKCS7 签名。但是,我不知道如何解码/阅读这些信息以便快速了解。

任何的想法?

谢谢,克里斯。

mkl*_*mkl 5

首先,不一定来自签名散列/摘要消息,在 PKCS#7 / CMS 签名的情况下,通常涉及多个散列,参见。这个对数字签名中pdf的消息摘要的回答

不过,考虑到您需要摘要来满足一些法律限制,我假设您是在ETSI.CAdES.detachedadbe.pkcs7.detached类型 PDF 签名的签名属性的值之后MessageDigest(如果存在)是摘要有符号字节范围。


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

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 
    }
}
Run Code Online (Sandbox Code Playgroud)

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

FirstPage11P0022AD_20150202164018_307494.pdf
  Signature1
    Digest algorithm: SHA1
    Hash: 4ac0ed7c2ec611d491f37b5ca74598237b85dbab
Run Code Online (Sandbox Code Playgroud)