引入:
在我们加密解密过程中,因为我上次在*上看到一篇文章http://en.wikipedia.org/wiki/Advanced_Encryption_Standard说,AES的加密方式支持的密钥是128位,192位和256位 ,而实际应用中,如果我用128位的AES密码加密,则没问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public static void main(String[] args) throws Exception {
//我们演示加密解密字符串
System.out.println( "加密解密字符串:" );
String stringNeedEncrypt= "加密这段文本" ;
System.out.println( "被加密的文本为:" +stringNeedEncrypt);
//产生一个密钥
KeyGenerator keyGen = KeyGenerator.getInstance( "AES" );
keyGen.init( 128 );
Key key=keyGen.generateKey();
System.out.println( "\n加密使用的密钥为:" +( new BASE64Encoder()).encode(key.getEncoded()));
System.out.println( "加密使用的算法为:" +key.getAlgorithm());
//加密字符串过程
System.out.println( "\n开始加密字符串..." );
byte [] encryptedValue = EncryptUtil.encryptString(stringNeedEncrypt, key);
System.out.println( "加密后的密文为:" +( new BASE64Encoder()).encode(encryptedValue));
//解密字符串过程
System.out.println( "\n开始解密字符串..." );
String decryptedString = EncryptUtil.decryptString(encryptedValue, key);
System.out.println( "解密后还原的字符串为:" +decryptedString);
}
|
显示结果为:
但是,如果我们把代码的第11行 ,keyGen.init改为256(也就是希望密码长度为256位),那么则会抛出以下的异常:
这是为什么呢?
解决:
这个问题是因为美国在用于加密的密钥上对于出口做了限制,它不提供很长的,非常高强度的密钥
因为我们的jdk版本是1.6
所以去http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html下载不限制密钥长度的策略文件。
接受完许可证协议后,下载jce_policy-6.zip文件到本地:
解压完毕后,吧其中的local_policy.jar和US_export_policy.jar 覆盖掉%JAVA_HOME%/jre/lib/security目录下的同名文件:
然后重新运行下我们的应用,就成功了。
分析:
为什么这种方法是可以呢?答案肯定在我们复制的2个jar文件中。
我们先比较下local_policy.jar文件的内容。
对于限制密钥强度的版本的local_policy.jar文件,在其中default_local.policy文件如下:
此外,还多一个文件叫exempt_local.policy文件,其内容为:
在MANIFEST.MF中,标识出密码强度(Crypto-Strength)为limited.
对于不限制密钥强度的版本的local_policy.jar文件,在其中的default_local.policy文件如下:
在MANIFEST.MF中,标识出密码强度(Crypto-Strength)为unlimited.
我们再比较下US_export_policy.jar文件中的内容:
对于限制密钥强度的版本的US_export_policy.jar文件,在其中default_local.policy文件如下:
对于非限制密钥强度的版本的US_export_policy.jar文件,在其中的default_local.policy文件如下:
所以,从上面可以看出,在默认的jdk提供的JCE policy文件和我们单独下载的无限制密钥强度的JCE policy文件,对于US_export_policy.jar文件是几乎完全一样的。只有local_policy.jar不同。其中默认JDK提供的是有密钥限制的。
那么这文件怎么读呢?我们从http://pages.cs.wisc.edu/~horwitz/java-docs/guide/security/jce/JCERefGuide.html中找到了答案。
其中,从最后一个permissionjavax.crypto.CryptoPermisson * ,128条目可以看出,在限制密钥强度版本,任意算法的密钥强度最多是128位,这就是为什么我们用128位可以正常工作,但是我们用256位就会报错。当我们用不受限密钥强度的local_policy.jar替换的时候,它的permission变成了 permissionjavax.crypto.CryptoAllPermission; 这表明对任意算法,密钥长度不受限制。
在运行时,当application/applet类通过getInstance()方法实例化Cipher类时,然后如果应用有相关联的permissionpolicy文件,则JCE 会检查permission policy 文件是否有一些条目,适用于getInstance()调用中相应的算法。如果有,则进行permission check,放行或者拒绝这次实例化。