我有一个使用256位AES加密的应用程序,Java开箱即用不支持。我知道要使其正常运行,我在security文件夹中安装了JCE不限强度的jars。作为开发人员,这对我来说很好,我可以安装它们。
我的问题是,由于将分发此应用程序,因此最终用户很可能不会安装这些策略文件。让最终用户下载这些文件只是为了使应用程序功能并不是一个有吸引力的解决方案。
有没有一种方法可以使我的应用程序运行而不会覆盖最终用户计算机上的文件?可以在不安装策略文件的情况下处理它的第三方软件?还是仅从JAR内引用这些策略文件的方法?
有两个通常引用的解决方案。不幸的是,这些都不是完全令人满意的:
Install the unlimited strength policy files
Skip the JCE API
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()在执行任何加密操作之前,只需从静态初始化程序等调用即可。
removeCryptographyRestrictions()
这JceSecurity.isRestricted = false就是直接使用256位密码所需的全部内容。但是,如果没有其他两项操作,Cipher.getMaxAllowedKeyLength()仍将继续报告128个,而256位TLS密码套件将不起作用。
JceSecurity.isRestricted = false
Cipher.getMaxAllowedKeyLength()
该代码可在Oracle Java 7和8上运行,并在不需要的Java 9和OpenJDK上自动跳过该过程。毕竟是一个丑陋的黑客,它可能无法在其他供应商的VM上运行。
它在Oracle Java 6上也不起作用,因为私有JCE类在那里被混淆了。但是,各个版本之间的混淆并不会改变,因此从技术上讲,仍然可以支持Java 6。
分享改善这个答案