我之前问过一个关于这个问题的问题,但它没有得到正确的回答,也没有任何结果。
我已经澄清了这个问题的一些细节,我真的很想听听你的想法,我该如何解决这个问题,或者我应该尝试什么。
我在我的Linux服务器上安装了Java 1.6.0.12,下面的代码可以完美地运行。
String key = "av45k1pfb024xa3bl359vsb4esortvks74sksr5oy4s5serondry84jsrryuhsr5ys49y5seri5shrdliheuirdygliurguiy5ru";
try {
Cipher c = Cipher.getInstance("ARCFOUR");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "ARCFOUR");
c.init(Cipher.DECRYPT_MODE, secretKeySpec);
return new String(c.doFinal(Hex.decodeHex(data.toCharArray())), "UTF-8");
} catch (InvalidKeyException e) {
throw new CryptoException(e);
}
今天我在我的服务器用户上安装了Java 1.6.0.26,当我试图运行我的应用程序时,我得到了以下异常。我的猜测是,这与Java安装配置有关,因为它在第一个版本中可以工作,但在后面的版本中不能工作。
Caused by: java.security.InvalidKeyException: Illegal key size or default parameters
at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
at javax.crypto.Cipher.a(DashoA13*..) ~[na:1.6]
at javax.crypto.Cipher.init(DashoA13*..) ~[na:1.6]
at javax.crypto.Cipher.init(DashoA13*..) ~[na:1.6]
at my.package.Something.decode(RC4Decoder.java:25) ~[my.package.jar:na]
... 5 common frames omitted
第25行是:
c.init(密码。DECRYPT_MODE secretKeySpec);
注:
* java。服务器的1.6.0.12 Java目录上的安全性与1.6.0.26 Java几乎完全匹配。安全文件。第一个中没有其他提供者。
*前一个问题在这里。
问题在于default_local文件的内容。如果您安装了jre,请在jre\lib\security文件夹中的local_policy.jar中的policy:
// 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;
};
如果您不需要全球有效设置,您可以简单地编辑此文件并将内容更改为
// Country-specific policy file for countries with no limits on crypto strength.
grant {
// There is no restriction to any algorithms.
permission javax.crypto.CryptoAllPermission;
};
这是你从Oracle下载JCE得到的结果。
在Java中,默认情况下AES支持128位密钥,如果你计划使用192位或256位密钥,Java编译器将抛出非法密钥大小异常,这是你得到的。
解决方案是victor & James建议的,你需要根据你的JRE版本(java6, java7或java8)下载JCE (Java密码扩展)。
JCE压缩包包含以下JAR:
local_policy.jar
US_export_policy.jar
您需要从<JAVA_HOME>/jre/lib/security中替换这些jar。
如果您是在Unix系统上,则可能是指/home/urs/usr/lib/jvm/java-<version>-oracle/
有时只是替换安全文件夹中的local_policy.jar, US_export_policy.jar在unix上不起作用,所以我建议先将安全文件夹复制到桌面,替换jar的@Desktop/security文件夹,从/jre/lib/删除安全文件夹,并将桌面安全文件夹移动到/jre/lib/。
例如::sudo mv security /usr/lib/jvm/java-7-oracle/jre/lib
默认情况下,Java只支持AES 128位(16字节)密钥大小的加密。如果您不需要支持超过默认值的密钥,您可以在使用Cipher之前将密钥修剪为适当的大小。有关默认支持的键,请参阅javadoc。
这是一个生成密钥的示例,该密钥可以在不修改策略文件的情况下使用任何JVM版本。请自行斟酌使用。
在AgileBits博客上有一篇关于128到256键大小是否重要的好文章
SecretKeySpec getKey() {
final pass = "47e7717f0f37ee72cb226278279aebef".getBytes("UTF-8");
final sha = MessageDigest.getInstance("SHA-256");
def key = sha.digest(pass);
// use only first 128 bit (16 bytes). By default Java only supports AES 128 bit key sizes for encryption.
// Updated jvm policies are required for 256 bit.
key = Arrays.copyOf(key, 16);
return new SecretKeySpec(key, AES);
}
这是一个只有代码的解决方案。不需要下载或混乱的配置文件。
这是一个基于反射的解决方案,在java 8上测试
在程序的早期调用此方法一次。
/ /进口
import javax.crypto.Cipher;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
/ /方法
public static void fixKeyLength() {
String errorString = "Failed manually overriding key-length permissions.";
int newMaxKeyLength;
try {
if ((newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES")) < 256) {
Class c = Class.forName("javax.crypto.CryptoAllPermissionCollection");
Constructor con = c.getDeclaredConstructor();
con.setAccessible(true);
Object allPermissionCollection = con.newInstance();
Field f = c.getDeclaredField("all_allowed");
f.setAccessible(true);
f.setBoolean(allPermissionCollection, true);
c = Class.forName("javax.crypto.CryptoPermissions");
con = c.getDeclaredConstructor();
con.setAccessible(true);
Object allPermissions = con.newInstance();
f = c.getDeclaredField("perms");
f.setAccessible(true);
((Map) f.get(allPermissions)).put("*", allPermissionCollection);
c = Class.forName("javax.crypto.JceSecurityManager");
f = c.getDeclaredField("defaultPolicy");
f.setAccessible(true);
Field mf = Field.class.getDeclaredField("modifiers");
mf.setAccessible(true);
mf.setInt(f, f.getModifiers() & ~Modifier.FINAL);
f.set(null, allPermissions);
newMaxKeyLength = Cipher.getMaxAllowedKeyLength("AES");
}
} catch (Exception e) {
throw new RuntimeException(errorString, e);
}
if (newMaxKeyLength < 256)
throw new RuntimeException(errorString); // hack failed
}
学分:Delthas
有两个选项可以解决这个问题
选项1:使用长度较短的证书RSA 2048
选项2:您将在jre\lib\security中更新两个jar
不管你用什么Java http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
或者使用IBM websphere或任何使用其java的应用程序服务器。
我遇到的主要问题是我使用了最大长度的认证,当我在websphere上部署耳朵时,抛出了相同的异常
Java Security: Illegal key size or default parameters?
我用两个罐子更新了websphere中的Java安装文件夹
https://www14.software.ibm.com/webapp/iwm/web/reg/pick.do?source=jcesdk&lang=en_US
你可以在https://www-01.ibm.com/support/docview.wss?uid=swg21663373链接中查看参考资料
如果您正在使用带有apt的Linux发行版并添加了webupd8 PPA,则可以简单地运行该命令
apt-get install oracle-java8-unlimited-jce-policy
其他更新:
The Unlimited Strength Jurisdiction Policy Files are included with Java 9 and used by default
Starting with Java 8 Update 161, Java 8 defaults to the Unlimited Strength Jurisdiction Policy.
Starting with Java 8 Update 151, the Unlimited Strength Jurisdiction Policy is included with Java 8 but not used by default. To enable it, you need to edit the java.security file in <java_home>/jre/lib/security (for JDK) or <java_home>/lib/security (for JRE). Uncomment (or include) the line
crypto.policy=unlimited
Make sure you edit the file using an editor run as administrator.
The policy change only takes effect after restarting the JVM
在Java 8 Update 151之前,其余的答案都是有效的。下载JCE无限强度管辖政策文件并替换。
更多细节,你可以参考我的个人博客文章下面-
如何安装Java密码扩展(JCE)无限强度权限策略文件