0

I'm trying to implement the signature of a PDF document with a HSM but can not get me the valid signature , and no longer can be failing. I searched the various issues that exist on this but I do not see the problem with my code.

I am using the following versions

<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.9</version>
        </dependency>   
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.47</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcmail-jdk15on</artifactId>
            <version>1.47</version>
        </dependency>

And my code is:

 public byte[] getHash() throws Exception {
     reader = new PdfReader(new ByteArrayInputStream(content));

     baos = new ByteArrayOutputStream();
     stamper = PdfStamper.createSignature(reader, baos, '\0');
     sap = stamper.getSignatureAppearance();

     sap.setReason("Test");
     sap.setLocation("On a server!");
     sap.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
     sap.setCertificate(x509Certificate);

     dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
     dic.setReason(sap.getReason());
     dic.setLocation(sap.getLocation());
     dic.setContact(sap.getContact());
     dic.setDate(new PdfDate(sap.getSignDate()));
     sap.setCryptoDictionary(dic);

     exc = new HashMap<PdfName, Integer>();
     exc.put(PdfName.CONTENTS, new Integer(8192 * 2 + 2));
     sap.preClose(exc);

     externalDigest = new ExternalDigest() {
         @Override
         public MessageDigest getMessageDigest(String hashAlgorithm)
                 throws GeneralSecurityException {
             return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
         }
     };

     chain = new X509Certificate[1];
     chain[0] = x509Certificate;

     sgn = new PdfPKCS7(null, chain, "SHA256", null, externalDigest, false);
     data = sap.getRangeStream();
     cal = Calendar.getInstance();
     hash = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));
     sh = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
     sh = DigestAlgorithms.digest(new ByteArrayInputStream(sh), externalDigest.getMessageDigest("SHA256"));
     return sh;
 }

 public void complateToSignature(byte[] signedHash) throws Exception {
    sgn.setExternalDigest(Base64.decode(signedHash), null, "RSA");
    encodedSig = sgn.getEncodedPKCS7(hash, cal, null, null, null, CryptoStandard.CMS);
    paddedSig = new byte[8192];
    System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);

    PdfDictionary dic2 = new PdfDictionary();
    dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));

    sap.close(dic2);

    byte[] pdf = baos.toByteArray();
    FileUtils.saveFileContent(pdf, Paths.get("pathFileDest.pdf"));
 }

Finally, my test code is:

private void signPdf(X509Certificate certificate){
    File pdf = new File("C:\\File8888.pdf");
    FileInputStream is;
    byte[] content = new byte[0];
    try {
        is = new FileInputStream(pdf);
        content = new byte[is.available()];
        is.read(content);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    PDFSignature1 operation = new PDFSignature1(content, certificate);

    byte[] hash = new byte[0];
    String encodeData = "";
    try {
        hash = operation.getHash();
         //simule control for mobile signature.
        encodeData = com.itextpdf.text.pdf.codec.Base64.encodeBytes(hash);
        if (encodeData.length() != 44) {
            throw new Exception("Sign to data must be 44 characters");
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    final String hashHex = toHex(encodeData);
    final String hashSignat = signExternalService(hashHex);

    try {
        operation.complateToSignature(hashSignat.getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

We did not get to see that we are wrong in the process.

We would greatly appreciate any help, or an alternative way to perform the process.

Thanks.

Desdenova
  • 5,326
  • 8
  • 37
  • 45
Kike MC
  • 1
  • 1
  • I don't understand your code. Where do you define your `KeyStore`? Why aren't you using PKCS#11? Did you even read [the documentation](http://pages.itextpdf.com/ebook-digital-signatures-for-pdf.html)? [This](http://developers.itextpdf.com/examples/security/digital-signatures-white-paper/digital-signatures-chapter-4#873-c4_01_signwithpkcs11hsm.java) is what your code should look like. – Bruno Lowagie Jun 29 '16 at 11:49
  • I closed the question referring to a question asking how to sign a PDF with a USB token. Your question is about signing with an HSM, and you might think that's a different question. It's not: signing with a USB stick or signing with an HSM is done the same way: using PKCS#11. As a matter of fact, the answer to the USB key explains how to sign a PDF with a Luna SA from SafeNet (that's a specific HSM). – Bruno Lowagie Jun 29 '16 at 11:58
  • First, I do not understand why it has closed the question if he has not understood . Second, the private key is housed in the HSM, so I do not have a PKCS#11. This process consists of generating the HASH string document to be signed, it is sent via web service to HSM and HSM itself with the certificate indicated, signature and returns that string. Finally, that string is inserted into the signature element of the PDF document. – Kike MC Jun 29 '16 at 13:12
  • I searched the forum and have not found a solution to this. Thank you very much for your attention. – Kike MC Jun 29 '16 at 13:12
  • I wrote the book on digital signatures. If you had written: the private key is stored on the HSM, so I can't use **PKCS#12**, you would have been correct. But if you say: the private key is stored on the HSM, so I can't use PKCS#11, you are completely wrong. PKCS#11 is the RSA standard that explains how to us private keys stored on devices. You have not read the free ebook on digital signatures. The question is closed because it was already adequately answered on StackOverflow. – Bruno Lowagie Jun 29 '16 at 13:34
  • If it was already answered, I could tell that topic is? Since you mentioned at the beginning of the question it has nothing to do with that presented here. Thank you very much. – Kike MC Jun 29 '16 at 13:42
  • I tried to follow the theme: "Sign PDF using an external service and iText", but I can not get a valid signature, so had asked for help here. – Kike MC Jun 29 '16 at 13:43
  • Have you read http://stackoverflow.com/questions/14831200/replace-signature-content-in-a-pdf/14833182#14833182 – Bruno Lowagie Jun 29 '16 at 14:07
  • Thank you very much, and sorry for the trouble. Have a nice day – Kike MC Jun 29 '16 at 14:19
  • Hello, reading the forum have seen this in one of your answers : However , with the way iText is Implemented Currently , the client 's certificate is Necessary . It is precisely this that trying to explain . What I have to do is send the HASH HASH and sign only that , since the HSM only allows me to do that. In the subject http://stackoverflow.com/questions/29210451/itext-generating-pdf-hash-without-certificate-chain/29211179#29211179 the same as trying to explain comments. – Kike MC Jun 29 '16 at 14:43
  • I understand the question. It's a pity you don't understand the answers. – Bruno Lowagie Jun 29 '16 at 18:47
  • Okay thank you very much. Your answers are very helpful for those who do not have their knowledge. I hope the rest of the forum really help them. – Kike MC Jun 30 '16 at 06:18
  • To summarize: if you want to sign a PDF *on the same machine as the HSM*, you use PKCS#11 as explained in [this answer](http://stackoverflow.com/a/28381632/1622493), If you want to sign a PDF anywhere and sign a hash on an HSM, you have to use the `signDeferred()` method as explained in [this answer](http://stackoverflow.com/a/29211179/1622493). **You can not technically sign a PDF without a public certificate,** but you can compose the hash that needs to be signed up-front and send that hash to the HSM for signing. – Bruno Lowagie Jun 30 '16 at 06:45
  • First of all, thank you very much for the reply. I'm testing with the theme you have shown me with "signDeferred". But it gives me a nullPointerException to launch signDeferred. I understand that is because I have the PrivateKey. Sorry for my doubts, I can not understand how I should do it. Currently, I reserve the space with "emptySignature" method, then I calculate the HASH and send it to HSM who signed me back chain, and finally call the method createSignature, but at this point gives me nullPointerException . I have read on the subject you've happened to me is the PrivateKey. – Kike MC Jun 30 '16 at 09:55
  • With `signDeferred()`, you don't need a `PrivateKey` in the application that signs the PDF. You just need to implement an `ExternalSignatureContainer`. In your case, that implementation doesn't need a `PrivateKey` either: it just needs to set up a connection with an application running on the HSM that signs bytes and returns the signed bytes. I don't understand why you write *I have read on the subject you've happened to me is the PrivateKey.* I respect people who aren't native English speakers (I'm not a native English speaker either), but that sentence doesn't make any sense to me. – Bruno Lowagie Jun 30 '16 at 10:50
  • Sorry for my English, I try to explain as best I can. I am implementing the solution you discussed me with signDeferred(); Thank you very much. – Kike MC Jul 01 '16 at 06:16
  • Hi, With the solution you discussed me (signDeferred()), now no indicate it me that the file has been modified after signed, now I'm getting an error like "Failed to decode BER". I have only to discard it signed chain problem. Someone can give me a little indication that may be the cause of this error? Thank you very much! – Kike MC Jul 04 '16 at 10:29

0 Answers0