Search code examples
javadigital-signaturebouncycastle

BouncyCastle - set custom alias to algorithm


I'm trying to verify signature digest using Bouncy Castle. The digest algorithm is SHA1.

Unfortunatelly the digest algorithm is set in the signature as SHA1WITHRSA (which is NOT a digest algorithm) instead of just SHA1.

There is nothing I can do about it.

Now I need to tell Bouncy Castle to use SHA1 when it encounters SHA1WITHRSA as a digest algorithm.

Is it possible to add an alias that would lead to SHA1 digest algorithm?

I tried this:

BouncyCastleProvider bcp = new BouncyCastleProvider();
bcp.put("Alg.Alias.MessageDigest.SHA1WITHRSA", "SHA-1");
bcp.put("Alg.Alias.MessageDigest.1.2.840.113549.1.1.5", "SHA-1");
Security.addProvider(bcp);

MessageDigest.getInstance("SHA1WITHRSA", "BC"); // throws an exception
MessageDigest.getInstance("1.2.840.113549.1.1.5", "BC"); // throws an exception

But with no success.. I'm getting java.security.NoSuchAlgorithmException.

The full stack is here:

no such algorithm: SHA1WITHRSA for provider BC
java.security.NoSuchAlgorithmException: no such algorithm: SHA1WITHRSA for provider BC
    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:227)
    at com.company.Main.testAddDigest(Main.java:82)
    at com.company.Main.main(Main.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

and the same for 1.2.840.113549.1.1.5

no such algorithm: 1.2.840.113549.1.1.5 for provider BC
java.security.NoSuchAlgorithmException: no such algorithm: 1.2.840.113549.1.1.5 for provider BC
    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:227)
    at com.company.Main.testAddDigest(Main.java:95)
    at com.company.Main.main(Main.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

There is no such digest algorithm SHA1WITHRSA, which makes it correct to throw the exceptions. But I thought that by adding the "put" lines, the aliases will be added and then the SHA1WITHRSA would be recognized as SHA1 digest algorithm.

UPDATE: It is working when I use the specific instance of Provider:

MessageDigest.getInstance("SHA1WITHRSA", bcp);

I'm not sure how to add the alias generally to all instances of BC not just the created bcp variable (BouncyCastleProvider). If it is even possible.


Solution

  • So, I've figured it out.

    I'm not sure anyone would meet scenario like this, but..

    The problem was that I was playing with the DSS (https://github.com/esig/dss, framework for handling digital signatures). It uses Bouncy Castle. I was testing it on a specific PDF which has its digest algorithm attribute set to SHA1withRSA (which is incorrect, there should be just SHA1). But the task was to process it as it has set the correct value - SHA1.

    So I needed to tell the bouncy castle to use SHA1 whenever it encounters SHA1withRSA set as a digest algorithm.

    I didn't want to modify the framework code too much (ideally not at all) and I certainly didn't want to modify any of the Bouncy Castle code.

    The following code solved it:

    BouncyCastleProvider bcp = (BouncyCastleProvider)Security.getProvider("BC");
    bcp.addAlgorithm("Alg.Alias.MessageDigest.SHA1WITHRSA", "SHA-1");
    bcp.addAlgorithm("Alg.Alias.MessageDigest.1.2.840.113549.1.1.5", "SHA-1");
    

    It gets the Bouncy Castle provider and adds two aliases routing to SHA-1 digest algorithm whenever the SHA1WITHRSA or 1.2.840.113549.1.1.5 is set as digest algorithm (which they are NOT!).

    One can argue that such PDF should not be verified, but that's different thing..