AES 属于对称加密
优点:算法公开、计算量小、加密速度快、加密效率高
缺点:密钥的管理和分发,困难,不够安全。因为双方都必须保存好密钥,有一方泄露数据就不安全。
=》适用场景:我的后台管理系统(1对1),这样既简单又合适。
注意:我使用的是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();
- }
效果图

首先导入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加密算法的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一致)