I have an app that uses 256-bit AES encryption which is not supported by Java out of the box. I know to get this to function correctly I install the JCE unlimited strength j
Bouncy Castle still requires jars installed as far as I can tell.
I did a little test and it seemed to confirm this:
http://www.bouncycastle.org/wiki/display/JA1/Frequently+Asked+Questions
Here is solution: http://middlesphere-1.blogspot.ru/2014/06/this-code-allows-to-break-limit-if.html
//this code allows to break limit if client jdk/jre has no unlimited policy files for JCE.
//it should be run once. So this static section is always execute during the class loading process.
//this code is useful when working with Bouncycastle library.
static {
try {
Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
field.setAccessible(true);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception ex) {
}
}
As of JDK 8u102, the posted solutions relying on reflection will no longer work: the field that these solutions set is now final
(https://bugs.openjdk.java.net/browse/JDK-8149417).
Looks like it's back to either (a) using Bouncy Castle, or (b) installing the JCE policy files.
Here is a modified version of @ntoskrnl's code featuring isRestrictedCryptography
check by actual Cipher.getMaxAllowedKeyLength, slf4j logging and support of singleton initialization from application bootstrap like this:
static {
UnlimitedKeyStrengthJurisdictionPolicy.ensure();
}
This code would correctly stop mangling with reflection when unlimited policy becomes available by default in Java 8u162 as @cranphin's answer predicts.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.NoSuchAlgorithmException;
import java.security.Permission;
import java.security.PermissionCollection;
import java.util.Map;
// https://stackoverflow.com/questions/1179672/how-to-avoid-installing-unlimited-strength-jce-policy-files-when-deploying-an
public class UnlimitedKeyStrengthJurisdictionPolicy {
private static final Logger log = LoggerFactory.getLogger(UnlimitedKeyStrengthJurisdictionPolicy.class);
private static boolean isRestrictedCryptography() throws NoSuchAlgorithmException {
return Cipher.getMaxAllowedKeyLength("AES/ECB/NoPadding") <= 128;
}
private static void removeCryptographyRestrictions() {
try {
if (!isRestrictedCryptography()) {
log.debug("Cryptography restrictions removal not needed");
return;
}
/*
* Do the following, but with reflection to bypass access checks:
*
* JceSecurity.isRestricted = false;
* JceSecurity.defaultPolicy.perms.clear();
* JceSecurity.defaultPolicy.add(CryptoAllPermission.INSTANCE);
*/
Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity");
Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions");
Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission");
Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
isRestrictedField.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(isRestrictedField, isRestrictedField.getModifiers() & ~Modifier.FINAL);
isRestrictedField.set(null, false);
Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy");
defaultPolicyField.setAccessible(true);
PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null);
Field perms = cryptoPermissions.getDeclaredField("perms");
perms.setAccessible(true);
((Map<?, ?>) perms.get(defaultPolicy)).clear();
Field instance = cryptoAllPermission.getDeclaredField("INSTANCE");
instance.setAccessible(true);
defaultPolicy.add((Permission) instance.get(null));
log.info("Successfully removed cryptography restrictions");
} catch (Exception e) {
log.warn("Failed to remove cryptography restrictions", e);
}
}
static {
removeCryptographyRestrictions();
}
public static void ensure() {
// just force loading of this class
}
}
For an alternative cryptography library, have a look at Bouncy Castle. It has AES and a lot of added functionality. It's a liberal open source library. You will have to use the lightweight, proprietary Bouncy Castle API for this to work though.