使用 iText 从 PCKS7 签名的 PDF 文件中获取 hash/digest
Obtaining the hash/digest from a PCKS7 signed PDF file with iText
我正在编写一个 Java Web 服务,该服务使用来自网络中某些客户端的 iText 签署 PDF 文档。文档被正确签名,并且可以使用外部工具进行验证。但是,由于某些法律限制,为了将此文档存储在官方文档存储库中,我必须提供签名中的 hash/digest 消息。
我几乎尝试了任何方法来获取该哈希值,但我能得到的最接近的方法是使用此代码片段将整个签名 (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 编码的 PKCS7 签名。但是,我不知道如何 decode/read 这个信息才能到达 hast。
有什么想法吗?
谢谢,
克里斯.
首先,在PKCS#7的情况下,不一定hash/digest消息来自签名 / CMS 签名通常涉及多个哈希,cf。 this answer to Message digest of pdf in digital signature.
考虑到您需要摘要来满足一些法律限制,不过,我假设您是在签名属性 MessageDigest
的值之后(如果它是目前)对于 ETSI.CAdES.detached 或 adbe。pkcs7.detached 类型的 PDF 签名是签名字节范围的摘要。
如果你想使用 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
}
}
你可以找到更完整的示例ExtractHash.java中使用的方法,它输出PDF文档中签名字段的gigest算法和摘要值,例如:
FirstPage11P0022AD_20150202164018_307494.pdf
Signature1
Digest algorithm: SHA1
Hash: 4ac0ed7c2ec611d491f37b5ca74598237b85dbab
我正在编写一个 Java Web 服务,该服务使用来自网络中某些客户端的 iText 签署 PDF 文档。文档被正确签名,并且可以使用外部工具进行验证。但是,由于某些法律限制,为了将此文档存储在官方文档存储库中,我必须提供签名中的 hash/digest 消息。
我几乎尝试了任何方法来获取该哈希值,但我能得到的最接近的方法是使用此代码片段将整个签名 (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 编码的 PKCS7 签名。但是,我不知道如何 decode/read 这个信息才能到达 hast。
有什么想法吗?
谢谢, 克里斯.
首先,在PKCS#7的情况下,不一定hash/digest消息来自签名 / CMS 签名通常涉及多个哈希,cf。 this answer to Message digest of pdf in digital signature.
考虑到您需要摘要来满足一些法律限制,不过,我假设您是在签名属性 MessageDigest
的值之后(如果它是目前)对于 ETSI.CAdES.detached 或 adbe。pkcs7.detached 类型的 PDF 签名是签名字节范围的摘要。
如果你想使用 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
}
}
你可以找到更完整的示例ExtractHash.java中使用的方法,它输出PDF文档中签名字段的gigest算法和摘要值,例如:
FirstPage11P0022AD_20150202164018_307494.pdf
Signature1
Digest algorithm: SHA1
Hash: 4ac0ed7c2ec611d491f37b5ca74598237b85dbab