Alex Chan
Alex Chan

Reputation: 11

MakeSignature.signDetached throws No Such Algorithm exception (SUN provider & SHA-256)

I am trying to digitally sign a PDF document with iText. Since I will be using a hardware encryptor with JCE provider eventually I am also trying to test getting rid of BountyCastle in my unit test and instead use the default SUN implementation for the time being (until the hardware encryptor arrives).

However, I get the following exception when I run my program:

Exception in thread "main" java.security.NoSuchAlgorithmException: no such algorithm: SHA256 for provider SUN at sun.security.jca.GetInstance.getService(GetInstance.java:87) at sun.security.jca.GetInstance.getInstance(GetInstance.java:206) at java.security.Security.getImpl(Security.java:698) at java.security.MessageDigest.getInstance(MessageDigest.java:215) at com.itextpdf.text.pdf.security.DigestAlgorithms.getMessageDigest(DigestAlgorithms.java:159) at com.itextpdf.text.pdf.security.ProviderDigest.getMessageDigest(ProviderDigest.java:61) at com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:130) at SignDoc.signPdf(SignDoc.java:142) at SignDoc.main(SignDoc.java:182)

The last few lines of codes are as below:

    //ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
    //ExternalDigest digest = new BouncyCastleDigest();
    //ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "SUN");
    ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "SunRsaSign");
    ExternalDigest digest = new ProviderDigest("SUN");
    MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);

As you can see, I am just copying the samples and changed the provider name and the call 'new BouncyCastleDigest()' to 'new ProviderDigest("SUN")'

Peeking at the source codes of iText (5.5.1-SNAPSHOT), I find the followings code fragments suspicious:

  1. MakeSignature.java line 142 - 145

    hashAlgorithm = externalSignature.getHashAlgorithm() is called and then used in

    DigestAlgorithms.digest(data, externalDigest.getMessageDigest(hashAlgorithm));

  2. PrivateKeySignature.java line 76

    Since I am using PrivateKeySignature, I peek at PrivateKeySignature.java and find that it returns its private class member hashAlgorithm and this is how it obtains the value during Construction (line 76):

    this.hashAlgorithm = DigestAlgorithms.getDigest(DigestAlgorithms.getAllowedDigests(hashAlgorithm));

  3. DigestAlgorithms.java methods getAllowedDigests() and getDigest()

    In turn, getAllowedDigests() returns the OID of the algorithm if the algorithm name is found in the allowedDigests hash map (2.16.840.1.101.3.4.2.1 in my case), otherwise it returns null.

    getDigest gets the digest name back from the OID using the digestNames hash map.

    However, the name in digestNames hash map that corresponds to the OID is SHA256, not SHA-256.

As a result, the final digest name got was "SHA256" as opposed to "SHA-256" and "SHA256" was causing the NoSuchAlgorithm exception in SUN provider.

(I tried getting a message digest instance directly using the SUN provider. It succeeded for SHA-256 but threw the same exception I am reporting here for SHA256.

Is this a problem with iText when using JCE providers other than BC?

Appreciate if anyone could shed some light on my problem.

Upvotes: 1

Views: 2317

Answers (1)

Alex Chan
Alex Chan

Reputation: 11

As a temporary workaround, I added the followings to PrivateKeySignature.java:

// Temporary fix - to remove hyphenation in hashAlgorithm name // String signMode = hashAlgorithm + "with" + encryptionAlgorithm; String signMode = hashAlgorithm.replaceAll("-","") + "with" + encryptionAlgorithm; // End Temporary fix

It works for me at least for now. Has to investigate how standard names of different algorithms in different context go before a long term solution can be devised, I believe.

Upvotes: 0

Related Questions