bouncycastle + JBoss AS7: JCE cannot authenticate the provider BC

mrzasa picture mrzasa · Mar 2, 2012 · Viewed 30.3k times · Source

I use BouncyCastle for encryption in my application. When I run it standalone, everything works fine. However, if I put it in the webapp and deploy on JBoss server, I get a following error:

javax.servlet.ServletException: error constructing MAC: java.security.NoSuchProviderException: JCE cannot authenticate the provider BC
(...)
root cause
java.lang.Exception: error constructing MAC: java.security.NoSuchProviderException: JCE cannot authenticate the provider BC
(...)
root cause
java.io.IOException: error constructing MAC: java.security.NoSuchProviderException: JCE cannot authenticate the provider BC
    org.bouncycastle.jce.provider.JDKPKCS12KeyStore.engineLoad(Unknown Source)
    java.security.KeyStore.load(Unknown Source)

Here is a part of the code that causes this error:

    if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null)
    {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    // Read the Private Key
    KeyStore ks = KeyStore.getInstance("PKCS12", BouncyCastleProvider.PROVIDER_NAME);
    ks.load(new FileInputStream(certificatePath), privateKeyPassword.toCharArray());

And maven dependency:

<dependency>
    <groupId>bouncycastle</groupId>
    <artifactId>bcmail-jdk16</artifactId>
    <version>140</version>
</dependency>

Do you know how could I deploy it?

Answer

James picture James · May 1, 2012

For JBoss AS7 bouncy castle needs to be deployed as a server module. This replaces the server/default/lib mechanism of earlier versions (as mentioned in Gergely Bacso's answer).

JBoss AS7 uses jdk1.6+. When using JBoss AS7 with jdk1.6 we need to make sure we are using bcprov-jdk16.

Create a Jboss module (a folder $JBOSS_HOME/modules/org/bouncycastle/main). Put the bouncy castle jars that you want to be globally available in it, along with a module.xml file that looks like this:

<module xmlns="urn:jboss:module:1.1" name="org.bouncycastle">
    <resources>
        <resource-root path="bcprov-jdk16-1.46.jar"/>
    </resources>
    <dependencies>
        <module name="javax.api" slot="main" export="true"/>
    </dependencies>
</module>

Once you have setup the module you need to make it available to your deployments. There are two ways:

1. Globally via standalone.xml

In $JBOSS_HOME/standalone/configuration/standalone.xml replace

<subsystem xmlns="urn:jboss:domain:ee:1.0"/>

with

<subsystem xmlns="urn:jboss:domain:ee:1.0">
    <global-modules>
        <module name="org.bouncycastle" slot="main"/>
    </global-modules>
</subsystem>

The jar libraries will now be available across all applications (and this will "emulate" adding to the classpath as was possible in jboss 4,5,6 etc)

2. For a specific deployment (preferred)

Add a module dependency entry to the ear's META-INF/jboss-deployment-structure.xml file, under the section, eg:

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
    <deployment>
        <dependencies>
            <module name="org.bouncycastle" slot="main" export="true" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>