一、傳輸加密
這里用 對稱加密模式 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);