混合加密方案
结合对称加密和非对称加密的优点,使用非对称加密来安全地交换对称加密的密钥,然后使用对称加密来加密实际的数据
对称加密算法
- AES (Advanced Encryption Standard): 目前最流行的对称加密算法之一,广泛应用于数据加密
- DES (Data Encryption Standard): 老牌的对称加密算法,但由于安全性问题,现在较少使用
- 3DES (Triple DES): DES的增强版,通过三次加密过程提高安全性
- Blowfish/Twofish: 另外两种对称加密算法,Blowfish较老,Twofish是其后继者。
非对称加密算法
- RSA: 广泛使用的非对称加密算法,适用于密钥交换和数字签名。
- ECC (Elliptic Curve Cryptography): 基于椭圆曲线数学的一种加密方法,较RSA更高效,适用于移动和嵌入式设备。
- Diffie-Hellman: 主要用于密钥交换,允许双方在不安全的通道上安全地交换密钥。
示例
PC登录加密
login页面获取公钥
created() { genPublicKey().then(res => { localStorage.setItem("publicRSA", res.data.publicKey) }) },
utils/index.js
import CryptoJS from "crypto-js";import JSEncrypt from "jsencrypt";// AES加密数据dataexport function aesEncrypt(data, AESKey) { const _key = CryptoJS.enc.Utf8.parse(AESKey); const encrypt = CryptoJS.AES.encrypt(JSON.stringify(data), _key, { // iv: iv, mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7, }); return encrypt.toString();}// 对AES秘钥加密(RSA加密)export function rsaEncrypt(publicKey, AESKey) { var encryptor = new JSEncrypt(); encryptor.setPublicKey(publicKey); //使用公钥加密 let plaintext = AESKey; return encryptor.encrypt(plaintext);}// WebSocket地址发生改变的情况export function newWebsock() { const url = window.location.host; console.log("环境", process.env.NODE_ENV, url); if (process.env.NODE_ENV == "production" && url != "192.168.0.161") { return "wss"; } else { return "ws"; }}/** * * @returns 生成不重复的随机序列号 '60a2cd4faec2474ca6ee43aac3b0bc1d' * 32位 16进制 */export function getUUID() { var d = new Date().getTime(); if (window.performance && typeof window.performance.now === "function") { d += performance.now(); //use high-precision timer if available } var uuid = "xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == "x" ? r : (r & 0x3) | 0x8).toString(16); }); return uuid;}
utils/request.js
// 在request拦截器中加
if (config.url == "/auth/login") { config.data = { data: aesEncrypt(config.data, AESKey), //加密后的data aesKey: rsaEncrypt(key, AESKey), //加密后的私销 publicKey: key, }; }
微信小程序-登录加密
utils/http.js
// 加解密const CryptoJS = require("crypto-js")const JSEncrypt = require("jsencrypt")/** * * 32位 16进制 */function getUUID() { var d = new Date().getTime(); var uuid = "xxxxxxxxxxxxxxxx".replace(/[x]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return r.toString(16); }); return uuid;}
let AESKey = getUUID()// AES加密数据datafunction aesEncrypt(data) { // 这样写的加密后在线工具可以正常解密,但是后台无法解密 // return CryptoJS.AES.encrypt(JSON.stringify(data), 'sQPoC/1do9BZMkg8I5c09A==').toString(); const _key = CryptoJS.enc.Utf8.parse(AESKey) //将秘钥转换成Utf8字节数组 //加密 const encrypt = CryptoJS.AES.encrypt(JSON.stringify(data), _key, { // iv: iv, mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }) return encrypt.toString()}//定义RSA加密函数,,对AES秘钥加密function rsaEncrypt(publicKey) { var encryptor = new JSEncrypt.JSEncrypt(); // 假设你已经获取到了后端提供的公钥字符串(key是Base64编码的公钥) encryptor.setPublicKey(publicKey); //使用公钥加密 return encryptor.encrypt(AESKey);}module.exports = (url, data, method = "GET", type) => { let data1 = data if (url == "/loginApi") { let PublicKey = '' if (!wx.getStorageSync("PublicKey")) { setTimeout(function () { wx.showToast({ title: '未获取到公钥,请退出重进', icon: 'none' }) }, 0) return } else { PublicKey = wx.getStorageSync("PublicKey") } data1 = { data: aesEncrypt(data), aesKey: rsaEncrypt(PublicKey), //加密后的私钥 publicKey: PublicKey }; } else { wx.showLoading({ title: '加载中...' }); } // 返回一个promise实例 return new Promise((resolve, reject) => { // 小程序请求 wx.request({ url: baseURL + url, data: data1, method: method, header: { 'content-type': type || '', Authorization: wx.getStorageSync("token"), }, success(res) { console.log('接口返回结果', res.data) if (res.statusCode == 200) { wx.hideLoading(); if (res.data.code == 200) { resolve(res.data); } else if (res.data.code == 401) { loginRedirect() } else { // 解决错误信息弹窗一闪而过 wx.showLoading(); wx.hideLoading(); setTimeout(function () { wx.showToast({ title: res.data.msg, icon: 'none', duration: 2000 }) }, 500) reject(res.data); //可以传入失败回调 } } else if (res.statusCode == 401) { loginRedirect() } else { wx.showToast({ title: '接口请求失败,接口状态' + res.statusCode, icon: 'none', duration: 2000 }) } }, fail() { wx.showToast({ title: '接口调取失败,请检查网络连接', icon: 'none', duration: 2000 }) }, complete() { wx.hideLoading(); } }) })}
**注意:**utils中要加jsencrypt.js文件,否则会找不到JSEncrypt报错信息