检查是否有无限密码
如何在Java代码中检查当前的JVM是否具有无限的强度encryption?
我想你可能可以使用Cipher.getMaxAllowedKeyLength() ,同时还可以将你使用的密码与已知的“好”,安全密码(如AES)列表进行比较。
这里有一篇参考文章 ,列出了Java 1.4以来的最大密钥大小pipe辖限制(这些可能没有改变,除非法律也改变 – 见下文)。
如果您在一个有encryption出口/import限制的国家运营,您必须咨询您所在国家/地区的法律,但在这些情况下假定您没有可用的无限强度encryption(默认情况下)在你的JVM中。 换句话说,假设您使用的是甲骨文公司的官方JVM ,而且您恰好居住在一个国家,美国已经对encryption的出口限制进行了调整(而且由于甲骨文是一家美国公司,它将受制于这些限制),那么你也可以假设在这种情况下,你没有无限的力量可用。
当然, 这并不妨碍你build立自己的 ,从而给予自己无限的力量,但根据你当地的法律,这可能是非法的。
这篇文章概述了从美国出口到其他国家的限制。
本着与丹·克鲁兹(DanCruz)的回答相同的精神,只用一行代码,而且没有任何例外:
boolean limit = Cipher.getMaxAllowedKeyLength("RC5")<256;
所以一个完整的程序可能是:
import javax.crypto.Cipher; public class TestUCE { public static void main(String args[]) throws Exception { boolean unlimited = Cipher.getMaxAllowedKeyLength("RC5") >= 256; System.out.println("Unlimited cryptography enabled: " + unlimited); } }
如果您在Linux上并且已经安装了JDK(但Beanshell不可用),则可以使用JDK提供的runscript命令进行检查。
jrunscript -e 'exit (javax.crypto.Cipher.getMaxAllowedKeyLength("RC5") >= 256);'; echo $?
如果无限制encryption可用,则返回1,否则为0。
Cipher.getMaxAllowedKeyLength
方法logging了如何检查限制的方法:
如果安装了JCE无限强度pipe辖权策略文件,则返回
Integer.MAX_VALUE
。
这意味着如果返回除(或实际上低于) Integer.MAX_VALUE
以外的任何值,则限制适用。
更多的信息在下面的方法的JavaDoc中:
/** * Determines if cryptography restrictions apply. * Restrictions apply if the value of {@link Cipher#getMaxAllowedKeyLength(String)} returns a value smaller than {@link Integer#MAX_VALUE} if there are any restrictions according to the JavaDoc of the method. * This method is used with the transform <code>"AES/CBC/PKCS5Padding"</code> as this is an often used algorithm that is <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#impl">an implementation requirement for Java SE</a>. * * @return <code>true</code> if restrictions apply, <code>false</code> otherwise */ public static boolean restrictedCryptography() { try { return Cipher.getMaxAllowedKeyLength("AES/CBC/PKCS5Padding") < Integer.MAX_VALUE; } catch (final NoSuchAlgorithmException e) { throw new IllegalStateException("The transform \"AES/CBC/PKCS5Padding\" is not available (the availability of this algorithm is mandatory for Java SE implementations)", e); } }
这是一个完整的复制粘贴版本,以允许testing
import javax.crypto.Cipher; import java.security.NoSuchAlgorithmException; class Test { public static void main(String[] args) { int allowedKeyLength = 0; try { allowedKeyLength = Cipher.getMaxAllowedKeyLength("AES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } System.out.println("The allowed key length for AES is: " + allowedKeyLength); } }
跑步
javac Test.java
java Test
如果JCE不工作输出: 128
JCE工作如下: 2147483647
如果您使用的是Linux,您可以使用此命令轻松检查
java -version ; \ echo 'System.err.println(javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding").getMaxAllowedKeyLength("AES"));' \ | java -cp /usr/share/java/bsh-*.jar bsh.Interpreter >/dev/null
如果输出是这样的话,那么无限强度的密码学是不可用的
java version "1.7.0_76" Java(TM) SE Runtime Environment (build 1.7.0_76-b13) Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode) 128
注意 :请使用jefflunt的答案或KonstantinSpirov的答案 。 这个答案不是一个有效的答案,因为它总是会返回true
。 我只是在这里留下这个答案,因为它被引用在答案和评论的其他地方,仅作为参考是有用的。
您可以使用以下方法初始化一个static final boolean
,然后您可以使用它来testing无限的encryption支持(因为只有在安装了无限制的策略时才支持AES 256位)。
boolean isUnlimitedSupported = false; try { KeyGenerator kgen = KeyGenerator.getInstance("AES", "SunJCE"); kgen.init(256); isUnlimitedSupported = true; } catch (NoSuchAlgorithmException e) { isUnlimitedSupported = false; } catch (NoSuchProviderException e) { isUnlimitedSupported = false; } System.out.println("isUnlimitedSupported=" + isUnlimitedSupported); // set static final variable = isUnlimitedSupported;
您可以通过使用groovy从命令行一步检查它:
groovysh -e 'javax.crypto.Cipher.getMaxAllowedKeyLength("AES")'
如果结果是2147483647
,那么您拥有无限encryption。
在旧版本的groovy上,你应该删除-e
:
groovysh 'javax.crypto.Cipher.getMaxAllowedKeyLength("AES")'
我最近不得不添加一个JCE检查,我的解决scheme发展到以下片段。 这是一个groovy脚本,但它应该很容易转换为标准的Java方法与try catch。 这已经通过Java 7和Java 8的testing。
import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.crypto.SecretKey; // Make a blank 256 Bit AES Key final SecretKey secretKey = new SecretKeySpec(new byte[32], "AES"); final Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); // This line will throw a invalid key length exception if you don't have // JCE Unlimited strength installed encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey); // If it makes it here, you have JCE installed