How to avoid installing “Unlimited Strength” JCE policy files when deploying an application?

前端 未结 11 2030
鱼传尺愫
鱼传尺愫 2020-11-22 07:43

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

相关标签:
11条回答
  • 2020-11-22 08:34

    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

    0 讨论(0)
  • 2020-11-22 08:35

    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) {
        }
    }
    
    0 讨论(0)
  • 2020-11-22 08:35

    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.

    0 讨论(0)
  • 2020-11-22 08:43

    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
        }
    }
    
    0 讨论(0)
  • 2020-11-22 08:46

    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.

    0 讨论(0)
提交回复
热议问题