2

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.

crigore
  • 400
  • 5
  • 23
  • My suggestion: to google "decode pkcs7 java" – Egl Apr 29 '15 at 10:37
  • @Egl Thanks for your help, but I'm still having problems. By googling your suggestion, I got a similar code to [link]https://www.bouncycastle.org/docs/pkixdocs1.4/org/bouncycastle/cms/CMSSignedData.html However, when trying to initialize CMSSignedData with my file I get a _org.bouncycastle.cms.CMSException: IOException reading content._ – crigore Apr 30 '15 at 14:41

1 Answers1

6

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
Community
  • 1
  • 1
mkl
  • 90,588
  • 15
  • 125
  • 265
  • You're a saver, thanks. I know that I shouldn't be extracting the digest, but I have to go on with these restrictions, despite hating them. – crigore Apr 30 '15 at 15:14
  • *I know that I shouldn't be extracting the digest* - that isn't a bad thing per se. I actually wonder why that information is hidden by iText classes. – mkl May 01 '15 at 10:22
  • Buy the way, if you think an answer is correct, you may want to accept it by clicking the tick on its left. – mkl May 01 '15 at 10:24
  • Done! Sorry, too new to using stackoverflow! Thanks again! – crigore May 04 '15 at 07:41