Java jce对aes算法有很好的支持,但是默认安装的JDK或者JRE是不能支持aes192bit密钥和aes256bit密钥两种算法的,需要到sun官方下载Java(TM) Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files,以下是jce unilimited strength jurisdiction policy files 6的官方下载地址:
下载后解压文件,将里面的文件拷贝到
<java-home>/lib/security [Unix]
<java-home>/lib/security [Win32]
覆盖原先的jar文件,请先备份原先的jar文件,以防你需要恢复密钥长度的限制,这里需要注意的是如果是安装的jdk,jdk目录中的jre下面的lib/security下的文件也需要覆盖。完成这个步骤之后就可以使用不限制密钥长度的aes算法了,简单的实现代码如下:
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(192); // 192 and 256 bits also available,这一步是否有安装jce unlimited strength jurisdiction policy files 都不会出现异常
Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);//这一步如果没有安装jce unlimited strength jurisdiction policy files,并且使用了192bits和256bits的密钥的话就会抛出java.security.InvalidKeyException:Invalid AES key length
byte[] output = cipher.doFinal(seed);//seed是一个byte[];
最后讲下aes算法是块加密运算的,单位块大小为16bytes,所以输入的byte[]如果不是16的倍数就填充至16的倍数,然后aes算法的密文结构就是aes对每一个块(16bytes)的明文加密的密文的拼串。比如aes128加密16bytes的byte[]a得到16bytes的密文a,加密16bytes的byte[]b得到16bytes的密文b,这样我们构建一个32bytes的byte[]c,前16bytes数据来自copy至a,后16bytes数据copy至b,这样将c输入aes128加密将得到一个32bytes的密文,并且就是之前的密文a和密文b的顺序拼串,以上都是nopadding模式下的情况。