Java:从applet修补AES256的客户端安全策略
问题内容:
我在商业Web应用程序中需要AES256加密/解密。当前,密钥大小为128时,一切都很好。从密码学上来说,这是不令人满意的,因此我的问题是如何最好地解决此问题,而无需用户手动安装任何东西。
我有来自Oracle的无限制管辖权的jar文件,但是我不知道替换用户JRE / lib /
security目录中的这些文件是否与旧版本兼容。显然,我不想破坏用户的JRE。另外,我对我的JRE安全目录具有写权限,但我假设某些用户将没有这些特权。
是否有解决此问题的简单方法,还是我坚持使用弱加密或对用户可能存在问题的步骤?
更新为“无限制” javax.crypto.JceSecurity
@ntoskml您是正确的。 getMaxAllowedKeyLength 仍返回有限的密钥大小,但是加密成功,密钥大小== 256
:)。如果可以使用强加密,我将更新测试方法并设置密钥大小。谢谢
>>> from javax.crypto import Cipher
>>> Cipher.getMaxAllowedKeyLength("AES")
128
>>> from java.lang import Class
>>> c = Class.forName("javax.crypto.JceSecurity")
>>> isRestricted = c.getDeclaredField("isRestricted")
>>> isRestricted.setAccessible(True)
>>> isRestricted.set(None, False)
>>> isRestricted.get(None)
False
>>> Cipher.getMaxAllowedKeyLength("AES")
128
>>> from javax.crypto import KeyGenerator
>>> kge = KeyGenerator.getInstance("AES")
>>> kge.init(256)
>>> aesKey = kgen.generateKey()
>>> c2 = Cipher.getInstance("AES")
>>> c2.init(Cipher.ENCRYPT_MODE, aesKey)
>>> c2.doFinal("test")
array('b', [-81, 99, -61, -51, 93, -42, -68, -28, 107, 59, -109, -98, -25, 127, 37, 23])
重新启动Jython控制台后的测试用例
>>> # Reflection as above
>>> isRestricted.get(None)
True
>>> kge.init(256)
>>> aesKey = kge.generateKey()
>>> c2.init(Cipher.ENCRYPT_MODE, aesKey)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011)
at javax.crypto.Cipher.implInit(Cipher.java:786)
at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
at javax.crypto.Cipher.init(Cipher.java:1213)
at javax.crypto.Cipher.init(Cipher.java:1153)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
java.security.InvalidKeyException: java.security.InvalidKeyException: Illegal key size or default parameters
宾果游戏:)感谢您分享@ntoskml
问题答案:
编辑:这是此问题的更新答案:在部署应用程序时如何避免安装“无限强度”JCE策略文件?
只需使用几行反射即可禁用密钥大小限制。我们在程序中使用此方法,该程序需要互操作性才能访问256位密码。
private static void removeCryptographyRestrictions() {
if (!isRestrictedCryptography()) {
return;
}
try {
java.lang.reflect.Field isRestricted;
try {
final Class<?> c = Class.forName("javax.crypto.JceSecurity");
isRestricted = c.getDeclaredField("isRestricted");
} catch (final ClassNotFoundException e) {
try {
// Java 6 has obfuscated JCE classes
final Class<?> c = Class.forName("javax.crypto.SunJCE_b");
isRestricted = c.getDeclaredField("g");
} catch (final ClassNotFoundException e2) {
throw e;
}
}
isRestricted.setAccessible(true);
isRestricted.set(null, false);
} catch (final Throwable e) {
logger.log(Level.WARNING,
"Failed to remove cryptography restrictions", e);
}
}
private static boolean isRestrictedCryptography() {
return "Java(TM) SE Runtime Environment"
.equals(System.getProperty("java.runtime.name"));
}
但是,我们的程序不是applet,并且我不确定applet是否可以访问反射API。
关于合法性的问题也仍然存在。有这个限制的原因。如果您担心,请咨询律师。
如果可能,请尝试将其保留为128位密钥。即使考虑摩尔定律,打破128位AES也会花费数十亿亿年。较长的密钥在现实世界中无济于事-
尤其是当密钥是从密码派生而来的时,密码无论如何都没有接近256位的熵。