想必大家遇到aes256加密报如下异常:java.security.InvalidKeyException: Illegal key size or default parameters,在网上搜到最多的解决方案是在oracle官网下载补丁jar包(local_policy.jar、US_export_policy.jar),进行替换。
当然,如果这个一个新项目,或者项目规模较小,完全可以通过替换对应jar包,或者升级jdk的版本来解决。但对于一个规模较大,稳定运行的项目,替换jar包可能意味着将系统推向潜在的未知的风险。
下面,通过反射来修改jdk对aes加密可以长度的限制
需要注意的是不同版本的jdk在实现有界限制的代码存在差异
测试jdk版本
此处使用openjdk
D:\test\springWorkspace>java -version
openjdk version "1.8.0_41"
OpenJDK Runtime Environment (build 1.8.0_41-b04)
OpenJDK Client VM (build 25.40-b25, mixed mode)
上实现代码
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;
import javax.crypto.Cipher;
import org.junit.jupiter.api.Test;
/**
* @author liujun
* @since 2022/5/17
*/
public class TestAes {
/**
* 去除jdk的128位的限制
*/
public static void removeCryptographyRestrictions() {
try {
/*
* Do the following, but with reflection to bypass access checks:
* JceSecurity.isRestricted = false;
* JceSecurity.defaultPolicy.perms.clear();
* JceSecurity.defaultPolicy.add(CryptoAllPermission.INSTANCE);
*/
final Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity");
final Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions");
final Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission");
final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
isRestrictedField.setAccessible(true);
// 去除isRestricted的final限制
final Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(isRestrictedField, isRestrictedField.getModifiers() & ~Modifier.FINAL);
isRestrictedField.set(null, false);
final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy");
defaultPolicyField.setAccessible(true);
final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null);
final Field perms = cryptoPermissions.getDeclaredField("perms");
perms.setAccessible(true);
((Map<?, ?>) perms.get(defaultPolicy)).clear();
final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE");
instance.setAccessible(true);
defaultPolicy.add((Permission) instance.get(null));
} catch (final Exception e) {
e.printStackTrace();
}
}
@Test
public void testGetLength() throws NoSuchAlgorithmException {
long length = Cipher.getMaxAllowedKeyLength("AES");
System.out.println("before:" + length);
removeCryptographyRestrictions();
length = Cipher.getMaxAllowedKeyLength("AES");
System.out.println("after:" + length);
}
}
输出
before:128
after:2147483647
需要注意的点
对于部分jdk版本"javax.crypto.JceSecurity"下的isRestricted是非final限制的,所以不需要额外处理去除final限制的代码。
参考文档:
https://stackoverflow.com/questions/1179672/how-to-avoid-installing-unlimited-strength-jce-policy-files-when-deploying-an
————————————————
原文链接:https://blog.csdn.net/weixin_39265427/article/details/106505502