28
votes

I am creating a swing based application in Java which uses some encryption technique. But javax.crypto.KeyGenerator.getInstance("AES", "BC") gives exception:

java.security.NoSuchProviderException: JCE cannot authenticate the provider BC
        at javax.crypto.SunJCE_b.a(DashoA13*..)
        at javax.crypto.KeyGenerator.getInstance(DashoA13*..)

So what is the problem?

7
This usually means you've done something wrong with packaging of the classes/jars and/or the classpath. You can't extract the BC classes from their jar and put them in another jar.President James K. Polk
Check you classpath, maybe you have several different versions of BouncyCastle JARs as it happened to me.Jaime Hablutzel

7 Answers

48
votes
  1. edit jre\lib\security\java.security
  2. add security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
  3. copy bc*.jar to jre\lib\ext
27
votes

To expand on the comment from GregS, all JCE provider JARs must be signed before they will be trusted by your Java runtime.

BouncyCastle dutifully supplies signed JARs that will work without a problem. However, if you extract class files from this JAR, or recompile the source, it will remove the signature and cause Java to reject the code.

See this related SO question: How to sign a custom JCE security provider

3
votes

For those finding this issue but actually using SpongyCastle, it might be interesting to know that on Android there is no such signature test and for your tests you can use SpongyCastle via the openJDK-8 as that doesn't care about signatures neither.

For reference, with SpongyCastle the error reads:

java.lang.SecurityException: JCE cannot authenticate the provider SC

More information in this issue

1
votes

We have been suffering with the same issue for a few weeks and had tried a lot of the suggested steps to no avail. Providing our solution below so others don't have to suffer like we did!

We were attempting to use bcprov-ext-jdk15on-162.jar, added to classpath, included in JBoss lib directories, bundled with WAR, marked as provided and added to JBoss /lib directories but no luck.

In the end, we tried different versions of bouncycastle and found a less recent version who's signature could be verified by our particular Java version's jarsigner (1.5X).

Despite the jar's signature being verifiable by our Java version, when the .jar is packaged into a WAR the signature was invalidated somehow by JBoss.

In the end, the solution for us was to;

1. Add bouncycastle jar to JBoss classpath
2. Add 'org.bouncycastle.jce.provider.BouncyCastleProvider' to 'java.security' providers
3. Mark bouncycastle in your WAR as a 'provided' dependency

Once we had a version of the .jar on our classpath and were sure that our WAR was not packaging it in we were golden.

The issue seems to be tightly coupled to whatever Java/JBoss version you happen to be using. So if this solution does not work for you I would suggest to test different versions of bouncycastle with

jarsigner -verify <bouncycastle.jar>
0
votes

For me the issue was bcprov-ext-jdk16.jar was being discarded by sbt assembly.

[warn] Merging 'META-INF/license/LICENSE.bouncycastle.txt' with strategy 'discard'
..
[warn] Merging 'META-INF/maven/org.jasypt/jasypt/pom.properties' with strategy 'discard'
[warn] Merging 'META-INF/maven/org.jasypt/jasypt/pom.xml' with strategy 'discard'
..

So I ended up using the bouncycastle.jar from -classpath as below,

java -Denvironment=dev -cp chat-server.jar:/Users/prayagupd/.ivy2/cache/org.bouncycastle/bcprov-ext-jdk16/jars/bcprov-ext-jdk16-1.46.jar com.chat.server.ChatServer

What also works is putting the bouncycastle.jar to $JAVA_HOME/jre/lib/ext,

cp /Users/prayagupd/.ivy2/cache/org.bouncycastle/bcprov-ext-jdk16/jars/bcprov-ext-jdk16-1.46.jar $JAVA_HOME/jre/lib/ext/

$ ls -l $JAVA_HOME/jre/lib/ext/
total 55208
-rw-r--r--  1 root  wheel   1887089 May  7 21:22 bcprov-ext-jdk16-1.46.jar
-rw-rw-r--  1 root  wheel   3860502 Sep  5  2017 cldrdata.jar
-rw-rw-r--  1 root  wheel      8286 Sep  5  2017 dnsns.jar
-rw-rw-r--  1 root  wheel     44516 Sep  5  2017 jaccess.jar
-rwxrwxr-x  1 root  wheel  18610276 Sep  5  2017 jfxrt.jar
-rw-rw-r--  1 root  wheel   1179093 Sep  5  2017 localedata.jar
-rw-rw-r--  1 root  wheel      1269 Sep  5  2017 meta-index
-rw-rw-r--  1 root  wheel   2022735 Sep  5  2017 nashorn.jar
-rw-rw-r--  1 root  wheel     41672 Sep  5  2017 sunec.jar
-rw-rw-r--  1 root  wheel    274148 Sep  5  2017 sunjce_provider.jar
-rw-rw-r--  1 root  wheel    248726 Sep  5  2017 sunpkcs11.jar
-rw-rw-r--  1 root  wheel     68924 Sep  5  2017 zipfs.jar
0
votes

FYI: instead of modifying java.security and copying jar to \jre\lib\ext, below steps resolved my issue as well.

  1. add Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()) in your class.
  2. add provided scope to bcprov.*.jar dependency in pom.xml.
  3. put bcprov.*.jar to your specific folder(e.g: \lib), then refer it when run the project.
0
votes

There are lot of solutions to this problem but unfortunately nobody talks about the causing issue.

If you are generating an executable jar that has BC.jar in it(in form of any dependency) than this issue would occur if below condition matches:

  1. Generating jar via eclipse's export option i.e. Export-> Runnable Jar File -> Libary Handling {extract required libraries into generated Jar}-> FINISH

Boom, now you have landed into trouble and you will face an error i.e. JCE can't authenticate the provider BC

The reason for above problem is, when you create a jar with option 1 than you are actually unpacking the BouncyCastle jar again that violates the security assosiated with BC. So, whenever you run it again java validates it and finds current BC.jar in your assosiated jar has an error.

So, guys make sure what you are doing is justified because by changing the JDK's security data that will make it work but not for everyone.

How to make it work?{This will work on local/personal machine only,not on every machine }

  1. edit jre\lib\security\java.security file
  2. add security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider
  3. copy bc*.jar to jre\lib\ext

That's it.