5

我需要在商业 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

4

2 回答 2

5

编辑:这是对这个问题的更新答案:如何在部署应用程序时避免安装“无限强度”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"));
}

但是,我们的程序不是小程序,我不确定小程序是否可以访问反射 API。

关于合法性的问题也仍然存在。这个限制是有原因的。如果您担心,请咨询律师。

如果可能,请尝试将其保留为 128 位密钥。即使考虑摩尔定律,打破 128 位 AES 也需要数十亿年的时间。更长的密钥在现实世界中没有任何好处——尤其是当密钥是从密码中派生出来的时,无论如何都没有接近 256 位的熵。

于 2013-08-26T05:09:31.830 回答
2

You are either stuck with the weak encryption or a potentially problematic step for users if you stick to the SunJCE.

There is obviously no problem importing an AES library, there is just a problem using it using an instance of Cipher. If you have a specific piece of software that does not depend on JCA, you can for instance rewrite it to use the lightweight crypto API of Bouncy Castle.

Note that many other parts of the Bouncy API themselves depend on the JCE. The lightweight API is also trickier to use and less documented/tested than the SunJCE.

The Bouncy Castle lightweight API is pretty large as well. It contains a lot of functionality that you won't need. So it is probably too large for your applet. If it is I would advice you to create a new library that only contains the specific classes that you need from Bouncy Castle. The Bouncy Castle is fortunately very liberally licensed. As long as you keep the copyright statements etc. in place, you can easily split it off.

于 2013-08-26T01:02:49.630 回答