Chi-Lan
Chi-Lan

Reputation: 3795

Checking if Unlimited Cryptography is available

How can I check, in Java code, if the current JVM have unlimited strength cryptography available?

Upvotes: 49

Views: 35978

Answers (9)

Igor Metz
Igor Metz

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

Maarten Bodewes
Maarten Bodewes

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

Ortomala Lokni
Ortomala Lokni

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

code
code

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

Michael Fuller
Michael Fuller

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

Go Dan
Go Dan

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

KonstantinSpirov
KonstantinSpirov

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

cklar
cklar

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

jefflunt
jefflunt

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

Related Questions