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

前端 未结 11 2247
鱼传尺愫
鱼传尺愫 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: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
        }
    }
    

提交回复
热议问题