0


前端使用 crypto-js 库 aes加解密

前端使用crypto-js AES 加密解密

CryptoJS是一个JavaScript加密算法库,用于在客户端浏览器中执行加密和解密操作。它提供了一系列常见的加密算法,如AES、DES、Triple DES、Rabbit、RC4、MD5、SHA-1等等。

AES

工作原理

AES(高级加密标准)是一种对称加密算法,即加密和解密使用相同的密钥。它可以加密长度为128、192和256位的数据块,并使用128位的密钥进行加密。AES算法使用了固定的块长度和密钥长度,并且被广泛应用于许多安全协议和标准中,例如SSL/TLS、SSH、IPSec等。

在AES加密中,明文被分成128位的块,每个块使用相同的密钥进行加密。加密过程包括以下步骤:

  • 密钥扩展:将密钥扩展为加密算法所需的轮密钥。
  • 初始轮:将明文分成块,并与第一轮密钥进行异或。
  • 多轮加密:将初始轮产生的结果反复进行多轮加密,每轮使用不同的轮密钥进行加密。
  • 最终轮:在最后一轮加密中,将块进行加密,但是不再进行下一轮加密,而是直接输出密文。

解密过程与加密过程类似,只是将加密过程中的步骤反过来。需要注意的是,解密的过程中使用的是相同的密钥和轮密钥。由于AES是一种块加密算法,因此在加密过程中,需要对数据进行填充,确保数据块大小为128位。

AES算法的优点
  • 安全性高:AES算法是一种可靠的加密算法,它在数据传输、文件加密和网络安全等领域有着广泛的应用。
  • 效率高:AES算法采用对称加密算法进行加密和解密,使用相同的密钥进行加密和解密。对称加密算法比非对称加密算法更加高效,因此AES算法具有更高的效率。
  • 应用广泛:AES算法在数据传输、文件加密和网络安全等领域有着广泛的应用。在数据传输过程中,AES算法可以对数据进行加密,保护数据的安全性。在文件加密过程中,AES算法可以对文件进行加密,保护文件的安全性。在网络安全领域,AES算法可以对网络数据进行加密,保护网络的安全性。

github地址: https://github.com/brix/crypto-js

cryptojs文档: https://cryptojs.gitbook.io/docs/#encoders

在线aes加密解密工具: http://tool.chacuo.net/cryptaes

安装

script 标签嵌入

<script src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.1.1/aes.min.js"></script>

npm 或 yarn 安装

npm install crypto-js

yarn add crypto-js

CommonJS

const CryptoJS =require('crypto-js');

ES module:

import CryptoJS from'crypto-js';
封装加密和解密
import CryptoJS from'crypto-js'// ------------AES-------------functiongetAesString(data, key, iv){//加密let keys = CryptoJS.enc.Utf8.parse(key)let vis = CryptoJS.enc.Utf8.parse(iv)let encrypt = CryptoJS.AES.encrypt(data, keys,{iv: vis,//iv偏移量 CBC需加偏移量mode: CryptoJS.mode.CBC,//CBC模式// mode: CryptoJS.mode.ECB, //ECB模式padding: CryptoJS.pad.Pkcs7 //padding处理});// debuggerreturn encrypt.toString();//加密完成后,转换成字符串}functiongetDAesString(encrypted, key, iv){// 解密var key  = CryptoJS.enc.Utf8.parse(key);var iv   = CryptoJS.enc.Utf8.parse(iv);var decrypted =CryptoJS.AES.decrypt(encrypted,key,{iv:iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.Pkcs7
   });return decrypted.toString(CryptoJS.enc.Utf8);}// AES 对称秘钥加密const aes ={en:(data, key)=>getAesString(data, key.key, key.iv),de:(data, key)=>getDAesString(data, key.key, key.iv)};// BASE64const base64 ={en:(data)=> CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data)),de:(data)=> CryptoJS.enc.Base64.parse(data).toString(CryptoJS.enc.Utf8)};// SHA256constsha256=(data)=>{return CryptoJS.SHA256(data).toString();};// MD5constmd5=(data)=>{return CryptoJS.MD5(data).toString();};export{ aes, md5, sha256, base64 };
使用 JSEncrypt 生成密钥

JSEncrypt是基于JavaScript的RSA加密库,允许在浏览器端使用RSA算法进行加密和解密操作。它提供了容易使用的API,简化了在客户端上进行加密的过程。

JSEncrypt支持以下操作:

  • 生成密钥对: 可以使用JSEncrypt生成RSA密钥对,包括公钥和私钥。
  • 加密: 使用公钥加密数据,确保只有拥有私钥的服务器才能解密。
  • 解密: 使用私钥解密被公钥加密过的数据。
  • 密钥格式: JSEncrypt支持多种密钥格式,包括PEM格式(基于Base64编码)。

使用JSEncrypt进行RSA加密的基本步骤如下:

  • 引入JSEncrypt库: 在HTML页面中引入JSEncrypt库的脚本文件。
  • 创建JSEncrypt对象: 使用JSEncrypt构造函数创建一个新的JSEncrypt对象。
  • 生成密钥对: 封装getKey()方法生成RSA密钥对,并将生成的私钥加密后传给后端。
  • 加密数据: 使用encrypt.encrypt(plainText)方法,将明文数据进行加密。
  • 解密数据: 在服务器端使用私钥进行解密,获取原始数据。

需要注意的是,由于JSEncrypt是在客户端上执行的,所以密钥在传输过程中可能会存在安全风险。为了确保数据的安全性,建议在客户端和服务器之间使用安全的通信协议进行数据传输,并在服务器端进行进一步的安全验证和处理。

import JSEncrypt from'jsencrypt'const encrypt =newJSEncrypt();let publicKey ='MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeCDcnFrS7DIRbvZLHreVUzaMbAFy2DYmioxBK606urY4rVR8IgLgUhnyw2/GQ99pyr8lGtqPeOoapantw1XwEVyi74MDxs4UDL8j4OZR1Es7HVGOB0GwKWobdU9cm/1iDwGyouSmijxKyAePg6KsLNgbjDPYZRS11bYEuZ8/RLQIDAQAB';
encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----'+ publicKey +'-----END PUBLIC KEY-----')constrandom=(length)=>{var str = Math.random().toString(36).substr(2);if(str.length>=length){return str.substr(0, length);}
  str +=random(length-str.length);return str;}exportconstrsaEncode=(src)=>{let data = encrypt.encrypt(src);// 加密return data
};exportconstgetKey=()=>{let key ={key:random(16),iv:random(16)};// 生成密钥let code =rsaEncode(key.key +','+ key.iv)// 给密钥加密,在将加密后的密钥传给后端
  window.codeArr = window.codeArr ||{}
  codeArr[code]= key
  return{
    key, code
  }};exportconstgetAesKey=(aes)=>{let key =JSON.parse(JSON.stringify(codeArr[aes]))delete codeArr[aes]return key
};

window.getKey = getKey
window.rsaEncode = rsaEncode

publicKey 可以通过发请求后端返回,也可以自己定义,要求前后端一致

封装 axios 拦截器进行加密解密
/**
 *
 * http配置
 *
 */// 引入axios以及element ui中的loading和message组件import{ aes }from"@/util/encrypt.js";import{ getKey, getAesKey }from"@/config/key.js";import axios from"axios";import store from"../store";import router from"../router/router";import{ Loading, Message }from"element-ui";import{ getSessStore, setSessStore }from"@/util/store";// 超时时间if(store.online) axios.defaults.timeout =20000;else axios.defaults.timeout =0;//跨域请求,允许保存cookie
axios.defaults.withCredentials =true;// 统一加解密const Unify ={// 统一加密方法en(data, key){// 1.aes加密let aesStr = aes.en(JSON.stringify(data), key);return aesStr;},// 统一解密de(aesStr, key){// 1.aes解密let dataStr = aes.de(aesStr, key);// 3.转json对象let data =JSON.parse(dataStr);return data;},};let loadinginstace;let cfg, msg;
msg ="服务器君开小差了,请稍后再试";functionens(data){// debuggerlet src =[...data];
  src =JSON.stringify(src);let dataJm = aes.en(src);return dataJm;}functiondes(data){// debuggerlet src =[...data];let dataJm = aes.de(src);
  dataJm =JSON.parse(dataJm);return dataJm;}const cancelToken = axios.CancelToken
const source = cancelToken.source()//HTTPrequest拦截
axios.interceptors.request.use(function(config){
    console.log(config.data,"加密前入参---");
    config.cancelToken = source.token;// 全局添加cancelToken
    loadinginstace = Loading.service({fullscreen:true,});if(store.getters.token){let info =getSessStore("token");// console.log("info", info);
      config.headers["Authorization"]="Bearer "+ info;// 让每个请求携带token-- ['X-Token']为自定义key 请根据实际情况自行修改}const contenttype = config.headers.common["Accept"];let types = contenttype.includes("application/json");let key =getKey();// 获取密钥
    config.headers["aes"]= key.code;// 将 aes 的 code 设置到请求头,传给后端解密
    config.headers["name"]="send";if(types){if(config.method =="post"|| config.method =="put"){if(config.data){
          config.headers["crypto"]=true;
          config.headers["content-type"]="application/json";let data ={body: config.data,};let dataJm = Unify.en(data, key.key);// 加密 post 请求参数
          config.data = dataJm;}}}return config;},(error)=>{return Promise.reject(error);});//HTTPresponse拦截
axios.interceptors.response.use((response)=>{
    loadinginstace.close();let res = response.data ||{};if(response.headers["date"]){
      store.commit("setServiceTime", response.headers.date);}if(res.crypto){try{let key =getAesKey(response.headers.aes);/// 拿到公钥加密字符串if(!key){message("获取密钥异常","error");return Promise.reject(res);}// debugger
        res = Unify.de(res.body, key);
        response.data = res;}catch(err){message("系统异常:"+ err.message,"error");return Promise.reject(err);}}// debuggerif(res.code ===1){message(res.msg,"error");return Promise.reject(res);}
    console.log(response,"解密后response");return response;},(error)=>{
    console.log("错误信息", error);
    loadinginstace.close();const res = error.response ||{};if(res.status ===478|| res.status ===403|| res.status ===401){let resMsg = res.data.msg ? res.data.msg : res.data.data
      if(res.status ===403){message('服务授权失败,请联系管理添加权限!',"error");}else{message(resMsg,"error");}let flg = res.data.msg.includes('当前登录状态已失效')if(res.status ===478&& flg){//token失效
        source.cancel('登录信息已过期');// 取消其他正在进行的请求
        store.dispatch("FedLogOut").then(()=>{
          router.push("/login");///test});}}elseif(res.status ===400){message(res.data.error_description,"error");}elseif(res.status ===202){//三方未绑定this.$router.push({path:"/",});}elseif(res.status ===503|| res.status ===504){//服务异常message(res.data,"error");}elseif((res.status ===401&& res.statusText =="Unauthorized")||
      res.data.error =="invalid_token"||
      res.data.error =="unauthorized"){//token失效
      store.dispatch("FedLogOut").then(()=>{
        router.push("/login");///test});}else{message(res.data.message,"error");}return Promise.reject(error);});exportfunctionmessage(text, type){let t = text ? text :"服务或网络异常!"Message({message: t,type: type,duration:30*1000,center:true,showClose:true});}exportdefault axios;

总结

加密: 使用 JSEncrypt 生成私钥

key

并将密钥

key

加密得到

code

, 使用

CryptoJS.AES.encrypt()

和 key 加密请求数据,将 加密后的

code

设置在请求头,后端获取加密后

code

进行解密得到私钥

key

,再对请求数据解密得到原始数据
解密: 前端获取响应头的key,通过解密 JSEncrypt 解密得到私钥

key

, 使用

CryptoJS.AES.decrypt()

方法对响应数据进行解密,得到原始数据


本文转载自: https://blog.csdn.net/a123456234/article/details/132348541
版权归原作者 你不讲 wood 所有, 如有侵权,请联系我们删除。

“前端使用 crypto-js 库 aes加解密”的评论:

还没有评论