AES 属于对称加密
优点:算法公开、计算量小、加密速度快、加密效率高
缺点:密钥的管理和分发,困难,不够安全。因为双方都必须保存好密钥,有一方泄露数据就不安全。
=》适用场景:我的后台管理系统(1对1),这样既简单又合适。
一、spring boot 中新建一个Aes工具类
注意:我使用的是PKCS5Padding填充方式,主要原因是它在jdk中是自带的,同时PKCS5 和7本质差不多。而 使用PKCS7Padding我一直没找到对应得依赖包。
@Slf4j
@Component
public class AesTool {
//前后端约定的 key
private static final String KEY = "bhd63ymfkfnu8ynk";
//参数分别代表 算法名称/加密模式/数据填充方式
private static String algorithmStr = "AES/CBC/PKCS5Padding";
//偏移量
private static String offsetStr = "0000000000000000";
private static byte[] ivByte = offsetStr.getBytes();
/**
* 加密
* @param content 加密的字符串
* @param encryptKey key值
* @return
* @throws Exception
*/
public static String encrypt(String content, String encryptKey) throws Exception {
/* Cipher类提供了针对加密和解密的密码 encrypt mode(加密模式) */
Cipher cipher = Cipher.getInstance(algorithmStr);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"),generateIV(ivByte));
byte[] b = cipher.doFinal(content.getBytes("utf-8"));
// 采用base64算法进行转码,避免出现中文乱码
return Base64.encodeBase64String(b);
}
/**
* 解密
* @param encryptStr 解密的字符串
* @param decryptKey key值
* @return
* @throws Exception
*/
public static String decrypt(String encryptStr, String decryptKey) throws Exception {
/* Cipher类提供了针对加密和解密的密码 decrypt mode(解密模式) */
Cipher cipher = Cipher.getInstance(algorithmStr);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"), generateIV(ivByte));
// 采用base64算法进行转码,避免出现中文乱码
byte[] encryptBytes = Base64.decodeBase64(encryptStr);
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes);
}
public static String myEncrypt(String content) throws Exception {
return encrypt(content, KEY);
}
public static String myDecrypt(String encryptStr) throws Exception {
return decrypt(encryptStr, KEY);
}
// 生成iv(应该就是偏移量)
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
return params;
}
}
在mian方法测试
Map map=new HashMap<String,String>();
map.put("中文","value");
map.put("hello","world");
String content = JSONObject.toJSONString(map);
System.out.println("加密前:" + content);
try {
String encrypt = AesTool.myEncrypt(content);
System.out.println("加密后:" + encrypt);
String decrypt = AesTool.myDecrypt(encrypt);
System.out.println("解密后:" + decrypt);
}catch (Exception e){
e.printStackTrace();
}
效果图
二、vue中加密
首先导入crypto-js这个支持AES加密的依赖库
npm install crypto-js
新建一个AesEncrypt 的js文件
import CryptoJS from "crypto-js"
//默认自定义的约定密钥(与后端密钥保持一致)
const KEY = CryptoJS.enc.Utf8.parse("bhd63ymfkfnu8ynk");// 内容可自定义 16位长度字符
const IV = CryptoJS.enc.Utf8.parse("0000000000000000"); // 密钥偏移量 16位长度字符
/**
* AES对称加密 (CBC模式,需要偏移量)
* @param {Object} params 明文参数
*/
export const encrypt = (str) => {
let key = KEY
let iv = IV
//明文
let srcs = CryptoJS.enc.Utf8.parse(str);
console.log("明文")
console.log(srcs);
//加密
var encrypt = CryptoJS.AES.encrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC, //AES加密模式
padding: CryptoJS.pad.Pkcs7 //填充方式,这里后端是5 也可以用
});
console.log("加密后");
console.log(encrypt);
console.log("base64加密");
console.log(CryptoJS.enc.Base64.stringify(encrypt.ciphertext))
return CryptoJS.enc.Base64.stringify(encrypt.ciphertext); //返回base64格式密文
}
三、AES-128-CBC 基础知识点
这个是使用AES加密算法的CBC模式,使用128位数据块为一组进行加密解密,
即16字节明文,对应16字节密文,
明文加密时,如果数据不够16字节,则会将数据补全剩余字节
-
若最后剩余的明文不够16字节,需要进行填充,通常采用PKCS7进行填充。比如最后缺3个字节,则填充3个字节的0x03;若最后缺10个字节,则填充10个字节的0x0a;
-
若明文正好是16个字节的整数倍,最后要再加入一个16字节0x10的组再进行加密
加密时需要的参数
1、传入要加密的明文
2、传入一个16字节的key(同后端key一致)
3、传入一个16字节的初始偏移向量IV (同后端key一致)