Java:从applet为AES256修补客户端安全策略

时间:2013-08-26 00:54:55

标签: java security encryption applet cryptography

我在商业网络应用程序中需要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

Bingo :)感谢分享@ntoskml

2 个答案:

答案 0 :(得分:5)

编辑:以下是此问题的更新答案:How to avoid installing "Unlimited Strength" JCE policy files when deploying an application?


可以通过使用几行反射来禁用键大小限制。我们在我们的程序中使用此方法,该方法需要访问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位的熵。

答案 1 :(得分:2)

如果你坚持使用SunJCE,你可能会遇到弱加密或用户的潜在问题。

导入AES库显然没有问题,使用Cipher实例时使用它只会出现问题。如果您有一个不依赖于JCA的特定软件,您可以重写它以使用Bouncy Castle的轻量级加密API。

请注意,Bouncy API的许多其他部分本身都依赖于JCE。与SunJCE相比,轻量级API使用起来比较复杂,文档/测试也较少。

Bouncy Castle轻量级API也很大。它包含许多您不需要的功能。所以它对你的applet来说可能太大了。如果是的话,我建议你创建一个新的库,它只包含你需要从Bouncy Castle获得的特定类。幸运的是,充气城堡非常宽松。只要您保留版权声明等,就可以轻松将其拆分。