背景
公司项目集成钉钉API时回调接口需要使用32位长(258bit)密钥解密服务器回传的加密信息,在代码执行至cipher.init(2, keySpec, iv)时报java.security.InvalidKeyException: Illegal key size错误。
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES");
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(this.aesKey, 0, 16));
cipher.init(2, keySpec, iv);
networkOrder = Base64.decodeBase64(text);
originalArr = cipher.doFinal(networkOrder);
} catch (Exception var9) {
throw new DingTalkEncryptException(900008);
}
解决方案
google到一系列文章提到jdk1.8前 java运行时环境读到的是受限的policy文件,限制了AES加密的密钥长度,需要下载载JCE无限制权限策略文件,原文引用如下:
异常原因:如果密钥大于128, 会抛出java.security.InvalidKeyException: Illegal key size 异常. 因为密钥长度是受限制的, java运行时环境读到的是受限的policy文件. 文件位于${java_home}/jre/lib/security, 这种限制是因为美国对软件出口的控制.
解决方案:去官方下载JCE无限制权限策略文件。
jdk 5: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html#jce_policy-1.5.0-oth-JPR
jdk6: http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JDK7的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件
如果安装了JDK,还要将两个jar文件也放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件。
侵删,引用自https://www.cnblogs.com/lilinzhiyu/p/8024100.html
但我项目中使用的JDK为11.0.12,尝试了上述方法发现没有解决问题,遂跟踪了一下代码,一直跟踪到JceSecurity.class的setupJurisdictionPolicies方法下,发现上述限制来自于jdk-11.0.12\conf\security\policy\limited\default_local.policy文件最后一行,遂将最后一行permission javax.crypto.CryptoPermission *, 128修改为permission javax.crypto.CryptoPermission *, 512; 顺利解决。
// Some countries have import limits on crypto strength. This policy file
// is worldwide importable.
grant {
permission javax.crypto.CryptoPermission "DES", 64;
permission javax.crypto.CryptoPermission "DESede", *;
permission javax.crypto.CryptoPermission "RC2", 128,
"javax.crypto.spec.RC2ParameterSpec", 128;
permission javax.crypto.CryptoPermission "RC4", 128;
permission javax.crypto.CryptoPermission "RC5", 128,
"javax.crypto.spec.RC5ParameterSpec", *, 12, *;
permission javax.crypto.CryptoPermission "RSA", *;
// permission javax.crypto.CryptoPermission *, 128;
permission javax.crypto.CryptoPermission *, 512;
};
总结
1、限制来源于jdk-11.0.12\conf\security\policy\limited\default_local.policy文件。
2、在代码中通过Security.setProperty(“crypto.policy”, “limited”)指定配置文件,并修改default_local.policy中最后一行的128为512顺利解决。
参考https://donaldhan.github.io/java/2020/08/07/JCE%E5%8A%A0%E5%AF%86%E6%9C%BA%E5%88%B6%E7%9A%84%E4%B8%80%E6%AC%A1%E5%A1%AB%E5%9D%91.html