JCA algorithm support
From version 4 of the Nimbus JOSE + JWT library virtually all crypto operations are performed via the standard Java crypto API. This abstraction permits easy plugin of alternative implementations (providers) for common cryptographic primitives and devices such as hardware security modules and smart cards.
JOSE algorithm support the Java
The stock JDK comes with a crypto provider which supports most standard JOSE
algorithms. For those algorithms that are not supported, like RSASSA-PSS
signatures (identified as JWS algorithms
will need to install an additional JCA provider (library). The open source
BouncyCastle is a popular choice for that.
Use the table below to check if a JOSE algorithm is supported by your Java runtime.
BouncyCastle is an open source Java library which implements a wide array of cryptographic algorithms, and where possible, they are made available via the standard JCA provider interface.
In terms of JOSE algorithm support, BouncyCastle can handle all those that are not covered out-of-the-box in Java 7 and 8.
How do you set up the BouncyCastle JCA provider in your application?
First, add a dependency to BouncyCastle 1.66 or a newer stable version in your project. If you use Maven:
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.66</version> </dependency>
Then, load the BouncyCastle JCA provider and add it to the list of the available providers in your Java runtime:
import java.security.Provider; import java.security.Security; import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton; Provider bc = BouncyCastleProviderSingleton.getInstance(); Security.addProvider(bc);
BouncyCastle for Android
Android comes with a stock shadowed BouncyCastle JCA provider which may be oudated or cut down in features depending on the Android version. If your Android application is getting JCA related runtime issues, such as missing API or cipher exceptions, there are two possible solutions:
Install an independent BouncyCastle JAR under a different JCA provider name. The MyBC utility can package a BouncyCastle JAR with a custom JCA provider name, package prefix and groupId for Maven.
Replace the stock BouncyCastle JCA provider with one imported via a direct dependency. Use to singleton utility to make sure the BC provider doesn't get loaded more than once, which can lead to significant memory leaks.
import java.security.Provider; import java.security.Security; import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton; Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME); Security.addProvider(BouncyCastleProviderSingleton.getInstance());
JWS and JWE algorithm support
The following table lists the JOSE algorithm support of the Java 7, Java 8 and BouncyCastle JCA providers.
|Algorithm family||Java 7||Java 8||Bouncy Castle|
|HS256, HS384, HS512||✓||✓||✓|
|RS256, RS384, RS512||✓||✓||✓|
|PS256, PS384, PS512||✗||✗||✓|
|ES256, ES384, ES512, ES256K||✓||✓||✓|
|A128KW, A192KW, A256KW||✓||✓||✓|
|ECDH-ES, ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW||✓||✓||✓|
|A128GCMKW, A192GCMKW, A256GCMKW||✗||✓||✓|
|PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW||✓||✓||✓|
|A128CBC-HS256, A192CBC-HS384, A256CBC-HS512||✓||✓||✓|
|A128GCM, A192GCM, A256GCM||✗||✓||✓|
|A128CBC+HS256, A256CBC+HS512 (deprecated)||✓||✓||✓|
Checking JOSE algorithm support programmatically
Version 4.3 of the library introduces a simple utility called JCASupport for checking whether a given JWS or JWE algorithm is supported by a JCA provider.
To check if the RSA-PSS signature algorithm PS256 is supported by the available JCA providers:
In Java 7 if you're using the default JCA providers you'll get a negative answer.
As we explained above, the open source BouncyCastle JCA provider has ready support for RSA-PSS signatures. Let's verify this:
Provider bc = BouncyCastleProviderSingleton.getInstance(); assert JCASupport.isSupported(JWSAlgorithm.PS256, bc);
Once loaded the BouncyCastle provider may be added to the global JCA provider list:
Security.addProvider(bc); assert JCASupport.isSupported(JWSAlgorithm.PS256);
If you don't want to add BouncyCastle globally, can just set it for the particular RSA signer / verifier instance that you intend to use:
RSASSASigner signer = new RSASSASigner(privateKey); signer.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance()); RSASSAVerifier verifier = new RSASSAVerifier(publicKey); verifier.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());