Reputation: 3795
How can I check, in Java code, if the current JVM have unlimited strength cryptography available?
Upvotes: 49
Views: 35978
Reputation: 451
If you are on Linux and you have installed the JDK (but Beanshell is not available), you can check with the runscript
command provided with the JDK.
jrunscript -e 'exit (javax.crypto.Cipher.getMaxAllowedKeyLength("RC5") >= 256 ? 0 : 1);'; echo $?
This returns a 0
status code if the Unlimited Cryptography is available, or 1
if not available. Zero is the correct 'success' return value for shell functions, and non-zero indicates a failure.
Upvotes: 45
Reputation: 93998
The way how to check if restrictions apply is documented in the method Cipher.getMaxAllowedKeyLength
:
If JCE unlimited strength jurisdiction policy files are installed,
Integer.MAX_VALUE
will be returned.
This means that if any value other than (or indeed lower than) Integer.MAX_VALUE
is returned that restrictions do apply.
Even more information is in the JavaDoc of the method below:
/**
* Determines if cryptography restrictions apply.
* Restrictions apply if the value of {@link Cipher#getMaxAllowedKeyLength(String)} returns a value smaller than {@link Integer#MAX_VALUE} if there are any restrictions according to the JavaDoc of the method.
* This method is used with the transform <code>"AES/CBC/PKCS5Padding"</code> as this is an often used algorithm that is <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#impl">an implementation requirement for Java SE</a>.
*
* @return <code>true</code> if restrictions apply, <code>false</code> otherwise
*/
public static boolean restrictedCryptography() {
try {
return Cipher.getMaxAllowedKeyLength("AES/CBC/PKCS5Padding") < Integer.MAX_VALUE;
} catch (final NoSuchAlgorithmException e) {
throw new IllegalStateException("The transform \"AES/CBC/PKCS5Padding\" is not available (the availability of this algorithm is mandatory for Java SE implementations)", e);
}
}
Note that since Java 9 the unlimited crypto policies are installed by default (with those affected by import / export regulations having to install the limited crypto policies instead). So this code would mainly be required for backwards compatibility and/or other runtimes.
Upvotes: 19
Reputation: 62585
You can check it in one step from the command line by using groovy :
groovysh -e 'javax.crypto.Cipher.getMaxAllowedKeyLength("AES")'
If the result is 2147483647
, you have unlimited cryptography.
On older version of groovy, you have to remove the -e
:
groovysh 'javax.crypto.Cipher.getMaxAllowedKeyLength("AES")'
Upvotes: 3
Reputation: 4231
This is a complete copy paste version to allow for testing
import javax.crypto.Cipher;
import java.security.NoSuchAlgorithmException;
class Test {
public static void main(String[] args) {
int allowedKeyLength = 0;
try {
allowedKeyLength = Cipher.getMaxAllowedKeyLength("AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
System.out.println("The allowed key length for AES is: " + allowedKeyLength);
}
}
To run
javac Test.java
java Test
If JCE is not working output: 128
JCE is working something like: 2147483647
Upvotes: 7
Reputation: 177
I recently had to do add a JCE check and my solution evolved to the following snippet. This was a groovy script, but it should be easy to convert to standard java method with a try catch. This has been tested with Java 7 & Java 8.
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.SecretKey;
// Make a blank 256 Bit AES Key
final SecretKey secretKey = new SecretKeySpec(new byte[32], "AES");
final Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// This line will throw a invalid key length exception if you don't have
// JCE Unlimited strength installed
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);
// If it makes it here, you have JCE installed
Upvotes: -1
Reputation: 15502
NOTE: Please use jefflunt's answer or KonstantinSpirov's answer. This answer is not a valid answer since it will always return true
. I am leaving this answer here only because it is referenced elsewhere in answers and comments and is useful as a reference only.
You could use the following to initialize a static final boolean
somewhere that you can then use for testing unlimited crypto support (since AES 256-bit is only supported if the unrestricted policy is installed).
boolean isUnlimitedSupported = false;
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES", "SunJCE");
kgen.init(256);
isUnlimitedSupported = true;
} catch (NoSuchAlgorithmException e) {
isUnlimitedSupported = false;
} catch (NoSuchProviderException e) {
isUnlimitedSupported = false;
}
System.out.println("isUnlimitedSupported=" + isUnlimitedSupported);
// set static final variable = isUnlimitedSupported;
Upvotes: 0
Reputation: 615
In the same spirit as the answer of Dan Cruz, but with a single line of code and without going trough exceptions:
boolean limit = Cipher.getMaxAllowedKeyLength("RC5")<256;
So a complete program might be:
import javax.crypto.Cipher;
public class TestUCE {
public static void main(String args[]) throws Exception {
boolean unlimited =
Cipher.getMaxAllowedKeyLength("RC5") >= 256;
System.out.println("Unlimited cryptography enabled: " + unlimited);
}
}
Upvotes: 48
Reputation: 73
If you are using Linux, you can check it easily with this command
java -version ; \
echo 'System.err.println(javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding").getMaxAllowedKeyLength("AES"));' \
| java -cp /usr/share/java/bsh-*.jar bsh.Interpreter >/dev/null
If the output is something like that, unlimited strength cryptography is not available
java version "1.7.0_76"
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)
128
Upvotes: 3
Reputation: 33954
I think you could probably use Cipher.getMaxAllowedKeyLength(), while also comparing the cypher you're using to known lists of "good", secure cyphers, such as AES.
Here's a reference article that lists maximum key size jurisdiction limitations that were current as of Java 1.4 (these likely haven't changed, unless the law has also changed - see below).
If you are operating in a nation that has cryptographic export/import restrictions, you'd have to consult the law in your nation, but it's probably safe to assume in these situations that you don't have unlimited strength cryptography available (by default) in your JVM. Putting it another way, assuming you're using the official JVM from Oracle, and you happen to live in a nation against which the U.S. has leveled export restrictions for cryptography (and since Oracle is a United States company, it would be subject to these restrictions), then you could also assume in this case that you don't have unlimited strength available.
Of course, that doesn't stop you from building your own, and thereby granting yourself unlimited strength, but depending on your local laws, that might be illegal.
This article outlines the restrictions on export to other nations, from the Unites States.
Upvotes: 25