23

I got the following error and I got a little stuck: Exception in thread "main"

java.security.InvalidKeyException: Illegal key size or default parameters
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011)
                at javax.crypto.Cipher.implInit(Cipher.java:786)
                at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
                at javax.crypto.Cipher.init(Cipher.java:1213)
                at javax.crypto.Cipher.init(Cipher.java:1153)
                at net.nakou.indie.wtext.engineClass.Session.cryptString(Session.java:52)

I'm stuck because all the answers I've found talk about the Java Cryptography Extension (JCE) which be normally included into the android SDK. So I think my problem is not this one.

I must have forgotten something, but I can't find what. Maybe my code is wrong (it's my first approach of cryptography in Java, I'm not an expert, and the following code is mostly some copy-pastes of tutorials).

I use this code to crypt and decrypt a String :

public String cryptString(String s) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException {
    byte[] KeyData = this.cryptKey.getBytes();
    SecretKeySpec KS = new SecretKeySpec(KeyData, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.ENCRYPT_MODE, KS);
    String ret = new String(cipher.doFinal(s.getBytes("UTF-8")));
    return ret;
}

public String decryptString(byte[] s) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    byte[] KeyData = this.cryptKey.getBytes();
    SecretKeySpec KS = new SecretKeySpec(KeyData, "Blowfish");
    Cipher cipher = Cipher.getInstance("Blowfish");
    cipher.init(Cipher.DECRYPT_MODE, KS);
    String ret = new String(cipher.doFinal(s));
    return ret;
}

And the following key :

private String cryptKey = "qkjll5@2md3gs5Q@FDFqf";

Thank you guys.

1
  • Long story short, no matter if it's a part of ADK, you need to change it all the same in the $java/jre/lib/security as any java application. Commented Jul 23, 2014 at 12:40

5 Answers 5

61

private String cryptKey = "qkjll5@2md3gs5Q@FDFqf";

By default Java supports only 128-bit encryption

128bits == 16Bytes == 16 Chars.

So cryptKey cannot exceed 16 characters.

If you want to exceed more than 16 character you have to install Java Cryptography Extension (JCE) Unlimited Strength.

Why 128bits?

Sign up to request clarification or add additional context in comments.

4 Comments

Can you explain also the reason?
@CaptainNakou These are part of JAVA
Ok, it works, thank you sir, hope this will work on mobile after the deployment into APK...
"It turns out that the Cipher class will generally not allow encryption with a key size of more than 128 bits. The apparent reason behind this is that some countries (although increasingly fewer) have restrictions on the permitted key strength of imported encryption software, although the actual number 128 is questionable. The good news is that: You can easily remove the restriction by overriding the security policy files with others that Sun provides."
11

There have been updates since Java 8/9

  1. The Unlimited Strength Jurisdiction Policy Files are included with Java 9 and used by default
  2. Starting with Java 8 Update 161, Java 8 defaults to the Unlimited Strength Jurisdiction Policy.
  3. Starting with Java 8 Update 151, the Unlimited Strength Jurisdiction Policy is included with Java 8 but not used by default. To enable it, you need to edit the java.security file in <java_home>/jre/lib/security (for JDK) or <java_home>/lib/security (for JRE). Uncomment (or include) the line

    crypto.policy=unlimited

    Make sure you edit the file using an editor run as administrator. The policy change only takes effect after restarting the JVM

Before Java 8 Update 151 you have to download JCE Unlimited Strength Jurisdiction Policy files and replace.

For more details see How to install Java Cryptography Extension (JCE) unlimited strength jurisdiction policy files

PS: Above link goes to my personal blog that has additional details.

Comments

3

Default JDK supports encryption only through 128 bit keys becuase of American restrictions. So to support encryption from 256 bit long key we have to replace local_policy.jar and US_export_policy.jars in $JAVA_HOME/java-8-oracle/jre/lib/security folder otherwise it will give java.security.InvalidKeyException: Illegal key size or default

Comments

2

This is a code only solution. No need to download or mess with configuration files.

It's a reflection based solution, tested on java 8

Call this method once, early in your program or while application is being started.

//Imports

import javax.crypto.Cipher;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;

//method

public static void fixKeyLength() {
    String errorString = "Failed manually overriding key-length permissions.";
    int newMaxKeyLength;
    try {
        if ((newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES")) < 256) {
            Class c = Class.forName("javax.crypto.CryptoAllPermissionCollection");
            Constructor con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object allPermissionCollection = con.newInstance();
            Field f = c.getDeclaredField("all_allowed");
            f.setAccessible(true);
            f.setBoolean(allPermissionCollection, true);

            c = Class.forName("javax.crypto.CryptoPermissions");
            con = c.getDeclaredConstructor();
            con.setAccessible(true);
            Object allPermissions = con.newInstance();
            f = c.getDeclaredField("perms");
            f.setAccessible(true);
            ((Map) f.get(allPermissions)).put("*", allPermissionCollection);

            c = Class.forName("javax.crypto.JceSecurityManager");
            f = c.getDeclaredField("defaultPolicy");
            f.setAccessible(true);
            Field mf = Field.class.getDeclaredField("modifiers");
            mf.setAccessible(true);
            mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
            f.set(null, allPermissions);

            newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES");
        }
    } catch (Exception e) {
        throw new RuntimeException(errorString, e);
    }
    if (newMaxKeyLength < 256)
        throw new RuntimeException(errorString); // hack failed
}

Comments

1

You can remove the maximum key restriction by replacing the existing JCE jars with unlimited strength policy jars.

For JAVA 8 the download JCE Jar from link - https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

(/usr/libexec/java_home -v to find Java_HOME in Mac)

Copy local_policy.jar and US_export_policy.jar extracted from above zip file to the $JAVA_HOME/jre/lib/security

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.