一、AES算法
对称加密算法是使用一个密钥进行加密和解密。AES算法是目前应用最广泛的对称加密算法。
AES算法的密钥长度有128位、192位和256位的,工作模式有ECB、CBC、PCBC、CTR等,填充模式有NoPadding、PKCS5Padding、PKCS7Padding等。
二、ECB工作模式
ECB模式需要一个固定长度的密钥,固定的明文会生成固定的密文。
//AES算法ECB模式
public class ECB {
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException {
String message = "是大眼同学呦!";// 原文信息
System.out.println("原始信息:" + message);
byte[] secretKey = "1234567890abcdef".getBytes();// 128位密钥(16字节)
// 加密:
byte[] data = message.getBytes();
byte[] encryped = encrypt(secretKey, data);
System.out.println("加密内容:" + Base64.getEncoder().encodeToString(encryped));
// 解密:
byte[] decrypted = decrypt(secretKey, encryped);
System.out.println("解密内容:" + new String(decrypted));
}
// 加密:传入参数密钥和原始内容的字节信息
public static byte[] encrypt(byte[] secretKey, byte[] input) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
// 创建密码对象,需要传入算法名称/工作模式/填充方式
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 根据secretKey(密钥)的字节内容,"恢复"秘钥对象
SecretKey keySpec = new SecretKeySpec(secretKey, "AES");
// 初始化秘钥:设置加密模式ENCRYPT_MODE
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
// 根据原始内容(字节),进行加密
return cipher.doFinal(input);
}
// 解密:传入参数密钥和机密后内容的字节信息
public static byte[] decrypt(byte[] secretKey, byte[] input) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
// 创建密码对象,需要传入算法名称/工作模式/填充方式
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 根据secretKey(密钥)的字节内容,"恢复"秘钥对象
SecretKey keySpec = new SecretKeySpec(secretKey, "AES");
初始化秘钥:设置加密模式DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec);
// 根据加密内容(字节),进行加密
return cipher.doFinal(input);
}
}
三、CBC工作模式
CBC工作模式需要一个随机数作为IV参数,这样对于同一份明文,每次生成的密文都不同。
//AES算法CBC工作模式
public class CBC {
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
String message = "是大眼同学呦!";// 原文信息
System.out.println("原始信息:" + message);
byte[] secretKey = "1234567890abcdef1234567890abcdef".getBytes();// 256位密钥(32字节)
// 加密:
byte[] data = message.getBytes();
byte[] encrypted = encrypt(secretKey, data);
System.out.println("加密内容:" + Base64.getEncoder().encodeToString(encrypted));
// 解密:
byte[] decrypted = decrypt(secretKey, encrypted);
System.out.println("解密内容:" + new String(decrypted));
}
// 加密:传入参数密钥和原始内容的字节信息
public static byte[] encrypt(byte[] secretKey, byte[] input)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
// 创建密码对象,需要传入算法名称/工作模式/填充方式
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 根据secretKey(密钥)的字节内容,"恢复"秘钥对象
SecretKey keySpec = new SecretKeySpec(secretKey, "AES");
// CBC模式需要生成一个16 bytes的initialization vector(IV参数 )
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] iv = sr.generateSeed(16);// 生成16个字节的随机数
System.out.println("IV参数:" + Arrays.toString(iv));// 输出IV参数
IvParameterSpec ivps = new IvParameterSpec(iv); // 随机数封装成IvParameterSpec参数对象
// 初始化秘钥:操作模式、秘钥、IV参数
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
// 根据原始内容(字节),进行加密
byte[] data = cipher.doFinal(input);
return join(iv, data);
}
// 解密:传入参数密钥和机密后内容的字节信息
public static byte[] decrypt(byte[] secretKey, byte[] input)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
// 把input分割成IV和密文
byte[] iv = new byte[16];
byte[] data = new byte[input.length - 16];
System.arraycopy(input, 0, iv, 0, 16);// IV参数
System.arraycopy(input, 16, data, 0, data.length);// 密文
System.out.println("IV参数:" + Arrays.toString(iv));// 输出IV参数
// 创建密码对象,需要传入算法名称/工作模式/填充方式
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 根据secretKey(密钥)的字节内容,"恢复"秘钥对象
SecretKey keySpec = new SecretKeySpec(secretKey, "AES");
// 回复IV参数
IvParameterSpec ivps = new IvParameterSpec(iv);
// 初始化秘钥:操作模式、秘钥、IV参数
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
return cipher.doFinal(data);
}
// 数组合并
public static byte[] join(byte[] arr1, byte[] arr2) {
byte[] arr = new byte[arr1.length + arr2.length];
System.arraycopy(arr1, 0, arr, 0, arr1.length);
System.arraycopy(arr2, 0, arr, arr1.length, arr2.length);
return arr;
}
}