问题
I'm writing a Java web service that signs PDF documents with iText from some clients in the network. Documents are being signed correctly, and can be verified with external tools. However, due to some legal restrictions in order to store this document in an official documentary repository I have to provide the hash/digest message from the signature.
I have tried almost anything to get to that hash, but the closest that I can get is to obtain the whole signature (CERT+HASH/DIGEST+TIMESTAMP) as a string with this code snippet (forgive the strings and [1] since I'm just testing how to do it):
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]);
With that I get a DER-enconded PKCS7 Signature, as far as I know. But, I don't know how to decode/read this info in order to get to the hast.
Any idea?
Thanks, Cris.
回答1:
First of all, there is not necessarily the hash/digest message from the signature, in case of PKCS#7 / CMS signatures usually multiple hashes are involved, cf. this answer to Message digest of pdf in digital signature.
Considering that you need the digest to fulfill some legal restrictions, though, I assume you are after the value of the signed attribute MessageDigest
which (if it is present) for ETSI.CAdES.detached or adbe.pkcs7.detached type PDF signatures is the digest of the signed byte ranges.
If you want to do that using iText classes (i.e. not security provider classes), you have to overcome the small issue that the value you are after is stored in a private member (PdfPKCS7.digestAttr
). Some reflection allows you to access it, though:
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
}
}
You can find the method used in a more complete example ExtractHash.java which outputs gigest algorithm and digest value of signature fields in a PDF document, e.g.:
FirstPage11P0022AD_20150202164018_307494.pdf
Signature1
Digest algorithm: SHA1
Hash: 4ac0ed7c2ec611d491f37b5ca74598237b85dbab
来源:https://stackoverflow.com/questions/29939831/obtaining-the-hash-digest-from-a-pcks7-signed-pdf-file-with-itext