对称加密算法现在流行的就几种如下:
DES (Data Encryption Standard) 有点老了。
3DES 是DES加密算法的一种模式。
AES (Advanced Encryption Standard)高级加密标准. 也是最流行的。所以今天就用代码实现它。
JAVA的JCE帮我们实现了AES的算法。我们只需要简单调用就可以了。
至于JCE,在JDK1.4就已经捆绑在JDK里了,这里不做过多解释,有兴趣的话可以自行百度JCA,JCE。
先上代码:
/**
* AES 对称加密方法
* @param input 待加密数据
* @param key 密钥key
* @param iv 初始IV
* @return 加密后数据
*/
public static byte[]aesEncrypt(byte[] input, byte[] key, byte[] iv) {
byte[] result =null;
// mode 1 加密 2 解密
int mode =1;
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
Key keySpec =new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec =new IvParameterSpec(iv);
cipher.init(mode, keySpec, ivSpec);
result = cipher.doFinal(input);
}catch (Exception e) {
e.printStackTrace();
}
return result;
}
代码很简单。这里解释一下参数"AES/CBC/PKCS5Padding"。
AES对加密数据进行分组操作的,16位数据一组。如果不满16位的话就要进行补齐。
PKCS5Padding 是一种补齐方式。补齐的数据是 (16 - 数据长度)。假如最后一组的数据长度是13,那么后边会补3个(16-13)=3。
下边是解密方法,和加密方法一摸一样,就是mode变成了2.
/**
* AES 解密方法
* @param input 加密数据
* @param key 密钥key
* @param iv 初始IV
* @return 解密数据
*/
public static byte []aesDecrypt(byte[] input, byte[] key, byte[] iv) {
byte[] result =null;
// mode 1 加密 2 解密
int mode =2;
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
Key keySpec =new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec =new IvParameterSpec(iv);
cipher.init(mode, keySpec, ivSpec);
result = cipher.doFinal(input);
}catch (Exception e) {
e.printStackTrace();
}
return result;
}
测试方法
public static void main(String[] args) {
String inputStr ="this is a String for AES";
byte[] key =generateKey(16);
byte[] iv =generateKey(16);
System.out.println("key = [" + Arrays.toString(key) +"]");
System.out.println("iv = [" + Arrays.toString(iv) +"]");
byte[] encrypedData =aesEncrypt(inputStr.getBytes(), key, iv);
System.out.println("encrypedData = [" + Arrays.toString(encrypedData) +"]");
String encrypedStr = Base64.getEncoder().encodeToString(encrypedData);
System.out.println("encrypedStr = [" + encrypedStr +"]");
byte[] decrypedData =aesDecrypt(encrypedData, key, iv);
System.out.println("decrypedStr = [" +new String(decrypedData) +"]");
}
/**
* 产生定长度数据
* @param length 长度
* @return 定长度数据
*/
public static byte[]generateKey(int length)
{
byte[] result =new byte[length];
Random rnd =new Random(System.nanoTime());
rnd.nextBytes(result);
return result;
}
输出结果
key = [[111, -60, -31, -36, -114, -21, 101, 62, -14, 63, -42, -84, 97, -58, 7, -105]]
iv = [[61, -17, 6, -122, -23, -71, 125, 53, -78, 42, 119, 31, 127, 83, 14, -60]]
encrypedData = [[-128, 68, -51, 115, 34, 39, 126, 19, 127, 41, 82, 4, 113, -20, -75, -20, -104, -61, 119, 61, 43, -29, -64, 72, 10, 119, 106, 83, -8, -80, 45, -93]]
encrypedStr = [gETNcyInfhN/KVIEcey17JjDdz0r48BICndqU/iwLaM=]
decrypedStr = [this is a String for AES]
再说一下 有AES_128,AES_192,AES_256几种方式加密。说白了就是密钥长度不同。
密钥越长,越难以破解。
我们这里怎么实现呢?只要把key的长度改一下就好了分别是 16,24,32.
由于我们是一个字节8位,对应过来正好是168=128,248=192,32*8=256.
byte[] key =generateKey(16);//AES_128
byte[] key =generateKey(24);//AES_192
byte[] key =generateKey(32);//AES_256