如何避免安装“无限力量"部署应用程序时的 JCE 策略文件? [英] How to avoid installing "Unlimited Strength" JCE policy files when deploying an application?

查看:25
本文介绍了如何避免安装“无限力量"部署应用程序时的 JCE 策略文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 256 位 AES 加密的应用程序,Java 不支持该应用程序.我知道要使其正常运行,我在安全文件夹中安装了 JCE 无限强度罐子.这对我作为开发人员来说很好,我可以安装它们.

I have an app that uses 256-bit AES encryption which is not supported by Java out of the box. I know to get this to function correctly I install the JCE unlimited strength jars in the security folder. This is fine for me being the developer, I can install them.

我的问题是,由于此应用程序将被分发,最终用户很可能不会安装这些策略文件.让最终用户下载这些只是为了使应用程序具有功能并不是一个有吸引力的解决方案.

My question is since this app will be distributed, end users most likely will not have these policy files installed. Having the end user download these just to make the app function is not an attractive solution.

有没有办法让我的应用程序在不覆盖最终用户机器上的文件的情况下运行?没有安装策略文件就可以处理它的第三方软件?或者只是从 JAR 中引用这些策略文件的方法?

Is there a way to make my app run without overwriting files on the end user machine? A third party software that can handle it without the policy files installed? Or a way to just reference these policy files from within a JAR?

推荐答案

这个问题有几个常用的解决方案.不幸的是,这些都不是完全令人满意的:

There are a couple of commonly quoted solutions to this problem. Unfortunately neither of these are entirely satisfactory:

  • 安装无限强度政策文件. 虽然这可能是您的开发工作站的正确解决方案,但让非技术用户在每台计算机上安装文件很快就会成为一个主要的麻烦(如果不是障碍的话).无法随您的程序分发文件;它们必须安装在 JRE 目录中(由于权限,该目录甚至可能是只读的).
  • 跳过 JCE API 并使用另一个加密库,例如 Bouncy Castle.这种方法需要一个额外的 1MB 库,这可能是一个很大的负担,具体取决于应用程序.复制标准库中包含的功能也感觉很愚蠢.显然,API 也与通常的 JCE 接口完全不同.(BC 确实实现了 JCE 提供程序,但这无济于事,因为在移交给实现之前应用了密钥强度限制.)此解决方案也不会让您使用 256 位 TLS(SSL) 密码套件,因为标准 TLS 库在内部调用 JCE 以确定任何限制.
  • Install the unlimited strength policy files. While this is probably the right solution for your development workstation, it quickly becomes a major hassle (if not a roadblock) to have non-technical users install the files on every computer. There is no way to distribute the files with your program; they must be installed in the JRE directory (which may even be read-only due to permissions).
  • Skip the JCE API and use another cryptography library such as Bouncy Castle. This approach requires an extra 1MB library, which may be a significant burden depending on the application. It also feels silly to duplicate functionality included in the standard libraries. Obviously, the API is also completely different from the usual JCE interface. (BC does implement a JCE provider, but that doesn't help because the key strength restrictions are applied before handing over to the implementation.) This solution also won't let you use 256-bit TLS (SSL) cipher suites, because the standard TLS libraries call the JCE internally to determine any restrictions.

但是还有反射.使用反射有什么不能做的吗?

But then there's reflection. Is there anything you can't do using reflection?

private static void removeCryptographyRestrictions() {
    if (!isRestrictedCryptography()) {
        logger.fine("Cryptography restrictions removal not needed");
        return;
    }
    try {
        /*
         * Do the following, but with reflection to bypass access checks:
         *
         * JceSecurity.isRestricted = false;
         * JceSecurity.defaultPolicy.perms.clear();
         * JceSecurity.defaultPolicy.add(CryptoAllPermission.INSTANCE);
         */
        final Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity");
        final Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions");
        final Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission");

        final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
        isRestrictedField.setAccessible(true);
        final Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(isRestrictedField, isRestrictedField.getModifiers() & ~Modifier.FINAL);
        isRestrictedField.set(null, false);

        final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy");
        defaultPolicyField.setAccessible(true);
        final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null);

        final Field perms = cryptoPermissions.getDeclaredField("perms");
        perms.setAccessible(true);
        ((Map<?, ?>) perms.get(defaultPolicy)).clear();

        final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE");
        instance.setAccessible(true);
        defaultPolicy.add((Permission) instance.get(null));

        logger.fine("Successfully removed cryptography restrictions");
    } catch (final Exception e) {
        logger.log(Level.WARNING, "Failed to remove cryptography restrictions", e);
    }
}

private static boolean isRestrictedCryptography() {
    // This matches Oracle Java 7 and 8, but not Java 9 or OpenJDK.
    final String name = System.getProperty("java.runtime.name");
    final String ver = System.getProperty("java.version");
    return name != null && name.equals("Java(TM) SE Runtime Environment")
            && ver != null && (ver.startsWith("1.7") || ver.startsWith("1.8"));
}

在执行任何加密操作之前,只需从静态初始化程序等调用 removeCryptographyRestrictions().

Simply call removeCryptographyRestrictions() from a static initializer or such before performing any cryptographic operations.

JceSecurity.isRestricted = false 部分是直接使用 256 位密码所需的全部内容;但是,如果没有其他两个操作,Cipher.getMaxAllowedKeyLength() 仍将继续报告 128,并且 256 位 TLS 密码套件将不起作用.

The JceSecurity.isRestricted = false part is all that is needed to use 256-bit ciphers directly; however, without the two other operations, Cipher.getMaxAllowedKeyLength() will still keep reporting 128, and 256-bit TLS cipher suites won't work.

此代码适用于 Oracle Java 7 和 8,并自动跳过 Java 9 和 OpenJDK 上不需要的过程.毕竟作为一个丑陋的黑客,它可能不适用于其他供应商的虚拟机.

This code works on Oracle Java 7 and 8, and automatically skips the process on Java 9 and OpenJDK where it's not needed. Being an ugly hack after all, it likely doesn't work on other vendors' VMs.

它也不适用于 Oracle Java 6,因为私有 JCE 类在那里被混淆了.不过,混淆不会因版本而异,因此从技术上讲,支持 Java 6 仍然是可能的.

It also doesn't work on Oracle Java 6, because the private JCE classes are obfuscated there. The obfuscation does not change from version to version though, so it is still technically possible to support Java 6.

这篇关于如何避免安装“无限力量"部署应用程序时的 JCE 策略文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆