Java:从小程序为 AES256 修补客户端安全策略 [英] Java: Patching client side security policy from applet for AES256
问题描述
我需要在商业 Web 应用程序中使用 AES256 加密/解密.目前一切都很好,密钥大小为 128.这在加密方面并不令人满意,所以我的问题是如何最好地解决这个问题,而不需要用户手动安装任何东西.
我有来自 Oracle 的无限权限 jar 文件,但我不知道在用户的 JRE/lib/security 目录中替换这些文件是否与旧版本兼容.显然我不想破坏用户的 JRE.此外,我对 JRE 安全目录有写权限,但我假设某些用户没有这些权限.
是否有解决此问题的简单方法,或者我是否坚持使用弱加密或对用户而言可能存在问题的步骤?
<小时>更新无限制"javax.crypto.JceSecurity
@ntoskml 你是对的.getMaxAllowedKeyLength 仍然返回有限的密钥大小,但加密成功,密钥大小 == 256 :).如果强加密可用,我将更新我的测试方法并设置密钥大小.谢谢
<预><代码>>>>从 javax.crypto 导入密码>>>Cipher.getMaxAllowedKeyLength("AES")128>>>从 java.lang 导入类>>>c = Class.forName("javax.crypto.JceSecurity")>>>isRestricted = c.getDeclaredField("isRestricted")>>>isRestricted.setAccessible(True)>>>isRestricted.set(无,假)>>>isRestricted.get(None)错误的>>>Cipher.getMaxAllowedKeyLength("AES")128>>>从 javax.crypto 导入 KeyGenerator>>>kge = KeyGenerator.getInstance("AES")>>>kge.init(256)>>>aesKey = kgen.generateKey()>>>c2 = Cipher.getInstance("AES")>>>c2.init(Cipher.ENCRYPT_MODE, aesKey)>>>c2.doFinal("测试")数组('b', [-81, 99, -61, -51, 93, -42, -68, -28, 107, 59, -109, -98, -25, 127, 37, 23])以及重启 Jython 控制台后的测试用例
<预><代码>>>># 反射如上>>>isRestricted.get(None)真的>>>kge.init(256)>>>aesKey = kge.generateKey()>>>c2.init(Cipher.ENCRYPT_MODE, aesKey)回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中在 javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1011)在 javax.crypto.Cipher.implInit(Cipher.java:786)在 javax.crypto.Cipher.chooseProvider(Cipher.java:849)在 javax.crypto.Cipher.init(Cipher.java:1213)在 javax.crypto.Cipher.init(Cipher.java:1153)在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)在 sun.reflect.NativeMethodAccessorImpl.invoke(来源不明)在 sun.reflect.DelegatingMethodAccessorImpl.invoke(来源不明)在 java.lang.reflect.Method.invoke(Unknown Source)java.security.InvalidKeyException: java.security.InvalidKeyException: 非法密钥大小或默认参数宾果游戏 :) 感谢分享@ntoskml
这里是这个问题的更新答案:如何避免安装无限强度"部署应用程序时的 JCE 策略文件?
<小时>只需使用几行反射就可以禁用密钥大小限制.我们在需要访问 256 位密码以实现互操作性目的的程序中使用此方法.
private static void removeCryptographyRestrictions() {如果 (!isRestrictedCryptography()) {返回;}尝试 {java.lang.reflect.Field isRestricted;尝试 {最终类>c = Class.forName("javax.crypto.JceSecurity");isRestricted = c.getDeclaredField("isRestricted");} catch (final ClassNotFoundException e) {尝试 {//Java 6 混淆了 JCE 类最终类>c = Class.forName("javax.crypto.SunJCE_b");isRestricted = c.getDeclaredField("g");} catch (final ClassNotFoundException e2) {扔e;}}isRestricted.setAccessible(true);isRestricted.set(null, false);} catch(最终的Throwable e){logger.log(Level.WARNING,未能删除密码限制",e);}}私有静态布尔值 isRestrictedCryptography() {返回Java(TM) SE 运行时环境".equals(System.getProperty("java.runtime.name"));}
但是,我们的程序不是小程序,我不确定小程序是否可以访问反射API.
关于合法性的问题仍然存在.这个限制是有原因的.如果您有疑虑,请咨询律师.
如果可能,尽量使用 128 位密钥.即使考虑到摩尔定律,打破 128 位 AES 也需要数十亿年的时间.更长的密钥在现实世界中没有任何好处 - 特别是当密钥来自密码时,无论如何都没有接近 256 位的熵.
I require AES256 encryption/decryption in a commercial web application. Currently everything is good with a key size of 128. This is not satisfactory cryptographically so my problem is how best to get round this issue without requiring the user to install anything manually.
I have the unlimited jurisdiction jar files from Oracle but I have no idea if replacing these in the user's JRE/lib/security directory will be compatible with older versions. Obviously I don't want to corrupt the user's JRE. Also I have write permission to my JRE security directory but I assume some user's will not have these privileges.
Is there a simple way around this issue, or am I stuck with either weak encryption or a potentially problematic step for users?
Update for "unrestricting" javax.crypto.JceSecurity
@ntoskml You are correct. getMaxAllowedKeyLength still returns the limited key size but the encryption succeeds with key size == 256 :). I will update my test method and set the key size if strong encryption is available. Thanks
>>> 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])
And the test case after restarting Jython console
>>> # 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
Bingo :) Thanks for sharing @ntoskml
EDIT: Here's an updated answer to this question: How to avoid installing "Unlimited Strength" JCE policy files when deploying an application?
It is possible to disable the key size restrictions simply by using a few lines of reflection. We use this method in our program which needs access to 256-bit cryptography for interoperability purposes.
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"));
}
However, our program is not an applet, and I am not sure whether applets have access to the reflection API.
The question about legality also remains. There is a reason for that limit. Consult a lawyer if you are concerned.
If possible, try to keep it to 128-bit keys. Even when taking Moore's law into consideration, breaking 128-bit AES would take billions upon billions of years. Longer keys offer no benefit in the real world – particularly when the keys are derived from passwords, which don't have anywhere near 256 bits of entropy anyway.
这篇关于Java:从小程序为 AES256 修补客户端安全策略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!