一、传输加密
这里用 对称加密模式 ASE实现。
React 前端
const CryptoJS = require("crypto-js");// 示例1:ECB模式(无需IV)
const encryptECB = (plainText, key) => {return CryptoJS.AES.encrypt(plainText, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}).toString();
};const decryptECB = (cipherText, key) => {const bytes = CryptoJS.AES.decrypt(cipherText, key, {mode: CryptoJS.mode.ECB});return bytes.toString(CryptoJS.enc.Utf8);
};// 示例2:CBC模式(需要IV)
const encryptCBC = (plainText, key, iv) => {return CryptoJS.AES.encrypt(plainText, key, {iv: CryptoJS.enc.Utf8.parse(iv),mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7}).toString();
};const decryptCBC = (cipherText, key, iv) => {const bytes = CryptoJS.AES.decrypt(cipherText, key, {iv: CryptoJS.enc.Utf8.parse(iv)});return bytes.toString(CryptoJS.enc.Utf8);
};// 测试用例
const key = "my-secret-key-123"; // 16/24/32字节
const iv = "1234567890123456"; // 16字节
const text = "Hello AES!";// ECB模式
const ecbEncrypted = encryptECB(text, key);
console.log("ECB加密结果:", ecbEncrypted);
console.log("ECB解密结果:", decryptECB(ecbEncrypted, key));// CBC模式
const cbcEncrypted = encryptCBC(text, key, iv);
console.log("CBC加密结果:", cbcEncrypted);
console.log("CBC解密结果:", decryptCBC(cbcEncrypted, key, iv));
Express 中间件
解密中间件封装
创建 AES_decrypt.js
中间件文件,处理请求体的加密数据:
const { AES_decrypt } = require('../utils/AES');
const decryptMiddleware = (req, res, next) => {if (req.body?.content && req.body?.iv) {try {const decrypted = AES_decrypt(req.body.content, req.body.iv);req.decryptedData = JSON.parse(decrypted); // 存储解密结果到请求对象next();} catch (err) {res.status(400).json({ error: "解密失败" });}} else {next(); // 非加密请求跳过}
};
module.exports = decryptMiddleware;
引用自实际中间件解密实现
在 utils/AES.js
中定义解密函数,需与前端 CryptoJS 的 CBC 模式配置一致:
const crypto = require('crypto');
const secretKey = '1234567890123456'; // 16字节密钥function AES_decrypt(encryptedText, ivHex) {const decipher = crypto.createDecipheriv('aes-128-cbc',Buffer.from(secretKey),Buffer.from(ivHex, 'hex'));let decrypted = decipher.update(encryptedText, 'base64', 'utf8');decrypted += decipher.final('utf8');return decrypted;
}
module.exports = { AES_decrypt };
下面是ECB(无vi模式)
const crypto = require('crypto');
const secretKey = process.env.AES_KEY || 'default16byteskey!'; // 16字节密钥module.exports = (req, res, next) => {if (req.body?.encryptedData) {try {const decipher = crypto.createDecipheriv('aes-128-ecb', Buffer.from(secretKey),null // ECB模式无需IV);let decrypted = decipher.update(req.body.encryptedData, 'base64', 'utf8');decrypted += decipher.final('utf8');req.decryptedBody = JSON.parse(decrypted);next();} catch (err) {res.status(400).json({ error: "ECB解密失败", details: err.message });}} else {next(); // 非加密请求跳过}
};
二、不可逆加密
这里用bcryptjs实现
import bcrypt from 'bcryptjs';/*** 加密(不可逆转加密)* @param rawData */
export const getHashedData = (rawData: string): string => {const salt = bcrypt.genSaltSync(10); // 成本因子推荐10-12const hashedData = bcrypt.hashSync(rawData, salt); return hashedData;
}/*** 匹配不可逆转加密方式生成的数据* @param rawData * @param hashedData * @returns */
export const matchHashDataAndRawData = (rawData: string, hashedData: string): boolean => {return bcrypt.compareSync(rawData, hashedData);
}
调用
加密
const hashedPassword = getHashedData(password);
比对数据
matchHashDataAndRawData(newPassword, password);