Java安全性:非法密钥大小或默认参数?
我之前曾经提过一个关于这个问题的问题,但没有得到正确的回答,而且没有得到任何答案。
所以我已经澄清了关于这个问题的一些细节,我真的很想听听你的想法,我该如何解决这个问题,或者我应该尝试什么。
我的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(Cipher.DECRYPT_MODE, secretKeySpec);
笔记:
*服务器的1.6.0.12 java目录中的java.security几乎与1.6.0.26 java.security文件完全匹配。 第一个没有额外的提供者。
*上一个问题在这里 。
最有可能你没有现在安装的无限强度文件。
您可能需要下载此文件:
Java密码扩展(JCE)无限强度管辖权策略文件6
Java加密扩展(JCE)无限强度管辖权政策文件7下载
Java密码扩展(JCE)无限强度管辖权政策文件8下载
从压缩包中提取jar文件并保存到${java.home}/jre/lib/security/ 。
JRE / JDK / Java 8权限文件可以在这里找到:
Java密码扩展(JCE)无限强度管辖权政策文件8下载
像詹姆斯上面所说:
安装${java.home}/jre/lib/security/ 。
对于JAVA 7,下载链接是jce-7-下载
复制Java \ jdk1.7.0_10 \ jre \ lib \ security中的两个下载的jar文件
把旧罐子放在安全的一边。
对于JAVA 8,下载链接是jce-8-download
复制Java \ jdk1.8.0_45 \ jre \ lib \ security下载的jar文件
把旧瓶子的备份放在安全的一边。
在使用Windows 7 x64,Eclipse和JDK 1.6.0_30时遇到同样的错误。 在JDK安装文件夹中有一个jre文件夹。 当我把上述的jar添加到JDK的lib / security文件夹中,没有运气的时候,这首先把我扔了。 完整路径:
C:\Program Files\Java\jdk1.6.0_30\jre\lib\security
将该归档的jce文件夹中包含的文件下载并解压到该文件夹中。
这是一个代码唯一的解决方案 。 无需下载或混乱的配置文件。
这是一个基于反射的解决方案, 在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
在Java中,默认情况下,AES支持128位密钥,如果您打算使用192位或256位密钥,java编译器会抛出非法的密钥大小异常,您将得到。
解决方案是作为胜利者和詹姆斯建议,您将需要按照您的JRE版本(java6,java7或java8)下载JCE(Java加密扩展)。
JCE zip包含以下JAR:
local_policy.jar
的US_export_policy.jar
您需要从/jre/lib/security替换这些jar。 如果你在unix系统上,可能会引用/home/urs/usr/lib/jvm/java--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
关于这个问题似乎有一个简短的讨论。 它链接的页面似乎已经消失,但其中一个响应可能是你所需要的:
事实上,从core / lib / jce复制US_export_policy.jar和local_policy.jar到$ JAVA_HOME / jre / lib / security有帮助。 谢谢。
问题是文件夹jre \ lib \ security中的local_policy.jar文件default_local.policy的内容 ,如果您安装了JRE:
// 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的话。
我也遇到了这个问题,但用下载的(从JCE)替换现有的一个解决了这个问题。 新的加密文件提供了无限的力量。
从Java 8u151和Java 9开始,您可以通过编程方式禁用该限制。
在较早的版本中,JCE辖区文件必须单独下载和安装,以允许JDK使用无限制加密。 下载和安装步骤不再需要。
相反,您现在可以在首次使用JCE类之前调用以下行(即最好在应用程序启动之后):
Security.setProperty("crypto.policy", "unlimited");
默认情况下,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); }
由于美国的限制,默认的JDK只支持通过128位密钥进行加密。 所以要支持从256位长密钥加密,我们必须替换$ JAVA_HOME / java-8-oracle / jre / lib / security文件夹中的local_policy.jar和US_export_policy.jars,否则会给出java.security.InvalidKeyException:非法密钥大小或默认
罐子和详细的概念可以从链接中了解:
easybook4u.com
谢谢,Sulabh Jain