,上面一篇文章介绍了使用DES方式进行加解密,我们说了DES由于使用8个字节(64bit)密钥进行加解密,所以安全性不够(当然这里的不够都是相对的),所以现在使用了密钥更多的AES方式进行对称加密提高安全性,AES加密方式的全称是Advanced Encryption Standard,这里的Advanced当然是相对于DES来说的。AES加密根据其使用的密钥长度又细分成AES-128、AES-192和AES-256这三种AES加密方式,其中AES-128对应128bit密钥长度,AES-192对应192bit,AES-256对应256bit,从道理上说密钥长度越长,机密的安全等级就越高,但是密钥越长加解密对硬件的性能消耗就越厉害,所以这里以AES-128为例来讲解AES加密方式在Java中的实现(实际上实现了128加密,另外两种也就简单了)。
1、AES加密
我们这里还是先实现AES的字节方式加密
/**
* AES加密二进制数据
*
* @param data 二进制待加密数据
* @param key 二进制密钥
* @return 二进制加密后的数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
//构造密钥生成器,指定AES算法
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
//根据传入的密钥字节生成一个可信任的随机数据源
SecureRandom secureRandom = new SecureRandom(key);
//初始化一个128的密钥生成器
keyGenerator.init(128,secureRandom);
//生成一个原始的对称密钥
SecretKey originSecretKey = keyGenerator.generateKey();
//根据原始对称密钥生成一个AES密钥
byte[] raw = originSecretKey.getEncoded();
SecretKeySpec secretKey = new SecretKeySpec(raw,"AES");
//声明一个Cipher对象
Cipher cipher = Cipher.getInstance("AES");
//使用密钥初始化cipher
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
//进行解密操作,实际上执行的还是Cipher的doFinal方法
return cipher.doFinal(data);
}
代码中对字节加密实现说的很详细了,这里提一下的就是由于这里使用了AES-128的加密方式,所以代码中的secretKey是16个字节(128bit)的,如果我们换成AES-192那么这里的secretKey就应该是24个字节。同时也要注意和DES实现加密一样,这里实际上的加密工作还是由Java中的Cipher类来完成的,我们所做的事情只不过是一些初始化的工作。
同样的,由于平时使用的都是针对字符串的加解密,所以这里得实现一个字符串的加密方法
/**
* 重载encrypt方法,使得数据源和密钥可使用字符串
*
* @param data 字符串数据源
* @param key 字符串密钥
* @return 返回字符串类型的
* @throws Exception
*/
public static String encrypt(String data, String key) throws Exception {
byte[] bt = encrypt(data.getBytes(), key.getBytes());
String str = Base64.encodeBase64URLSafeString(bt);
return str;
}
这里还是使用了Base64进行byte和String之间的转换,不能直接用new String(bytes)方式来转换,具体原因见DES那篇文章。
2、AES解密
同样的,这里来实现AES的字节解密方式
/**
* AES解密二进制数据
*
* @param data AES机密过的二进制数据
* @param key 用来解密的二进制密钥
* @return 返回解密后的数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
//构造密钥生成器,指定AES算法
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
//根据传入的密钥字节生成一个可信任的随机数据源
SecureRandom secureRandom = new SecureRandom(key);
//初始化一个128的密钥生成器
keyGenerator.init(128,secureRandom);
//生成一个原始的对称密钥
SecretKey originSecretKey = keyGenerator.generateKey();
//根据原始对称密钥生成一个AES密钥
byte[] raw = originSecretKey.getEncoded();
SecretKeySpec secretKey = new SecretKeySpec(raw,"AES");
//声明一个Cipher对象
Cipher cipher = Cipher.getInstance("AES");
/***到这里的字节解密代码都和机密代码一样***/
//使用密钥初始化cipher,这里和加密操作的唯一区别是设置的MODE不一样
cipher.init(Cipher.DECRYPT_MODE, secretKey);
//进行解密操作,实际上执行的还是Cipher的doFinal方法
return cipher.doFinal(data);
}
看的出来,这里的字节解密方法实现和加密方法实现只有cipher.init代码设置的Mode方式不一样而已,最后还是通过Cipher类来进行的解密操作。
这里还是来实现一个针对字符串的解密方式
/**
* 重载decrypt方法,输入加密过的数据源和密钥输出解密后的字符串
* @param data 加密后的字符串数据源
* @param key 用来加密的字符串密钥
* @return 解密后的字符串
* @throws Exception
*/
public static String decrypt(String data, String key) throws Exception {
byte[] buf = Base64.decodeBase64(data);
byte[] bt = decrypt(buf, key.getBytes());
return new String(bt);
}
到这里AES方式在Java中实现加解密的功能就算完成了,至于AES加解密的详情这里就细究了,毕竟DES的实现原理博主都觉得一时半会搞不定更不用说更加复杂的AES了。有了加解密方法,小伙伴们就很容易实现自己的AesUtil工具类了,不过在android中请记得用android.util.Base64的对应方法来处理Byte和String。