由于公司的业务改变,陆续的要将自建机房慢慢撤掉,业务系统迁往阿里云上进行部署。就在迁移SSO网关时,遇到一个比较头疼的问题,项目配置没变,唯一不同的就是阿里云上的CentOS操作系统与现有机房的虚拟机CentOS系统不一样,在阿里云的环境上抛出“java.security.InvalidKeyException: Illegal key size”的异常,导致用户无法登录,无法完成JWT的加密操作。
try {
if (provider != null) {
cipher = Cipher.getInstance("AES/GCM/NoPadding", provider);
} else {
cipher = Cipher.getInstance("AES/GCM/NoPadding");
}
GCMParameterSpec gcmSpec = new GCMParameterSpec(AUTH_TAG_BIT_LENGTH, iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmSpec); // 此行抛出异常
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new JOSEException("Couldn't create AES/GCM/NoPadding cipher: " + e.getMessage(), e);
} catch (NoClassDefFoundError e) {
// We have Java 6, GCMParameterSpec not available,
// switch to BouncyCastle API
return LegacyAESGCM.encrypt(secretKey, iv, plainText, authData);
}
网上百度了一番,也算是找到解决办法了。至于产生错误的原因,网上给出的解释我觉得还是比较牵强,虽然目前还没有定位到问题产生的根本原因。下面引用网上对该异常产生的原因阐述:
异常原因:如果密钥大于128,会抛出java.security.InvalidKeyException: Illegal key size 异常.。因为密钥长度是受限制的,java运行时环境读到的是受限的policy文件,文件位于${java_home}/jre/lib/security,这种限制是因为美国对软件出口的控制。
jar包和项目配置文件都是直接拷贝过去的,相同的JRE安装包,所以应该是操作系统的一些设置影响了JRE的一些配置,我觉得这是根本原因,但具体是操作系统的哪个配置影响的,暂时还没定位到。下面给出解决方案。
去官方网站下载JCE无限制策略文件,各版本的JRE/JDK下载链接如下:
- JDK6:https://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
- JDK7:https://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
- JDK8:https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
下载后解压,可看到local_policy.jar和US_export_policy.jar以及readme.txt三个文件。
接下来就是替换JRE/JDK的策略文件了(保险起见,先备份随JRE/JDK分发安装的local_policy.jar和US_export_policy.jar):
- 如果安装的是JRE,则将local_policy.jar和US_export_policy.jar拷贝到{JRE_HOME}\lib\security目录下覆盖原文件。
- 如果安装的是JDK,则将local_policy.jar和US_export_policy.jar拷贝到{JDK_HOME}\jre\lib\security目录下覆盖原文件。
最后,需要重启你的应用容器(例如Tomcat),如果是Spring boot项目,则重启项目即可。