混合加密(对称加密&非对称加密)

179 阅读3分钟

混合加密方案

结合对称加密和非对称加密的优点,使用非对称加密来安全地交换对称加密的密钥,然后使用对称加密来加密实际的数据

对称加密算法

  • 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' * 3216进制 */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")/** * * 3216进制 */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报错信息