前言
因公司现有后台管理系统项目需对部分网络请求接口的重要数据进行加密,整合了一套简单的基于 RSA + AES 加密机制的前端解决方案。
参考文献:
- crypto 廖雪峰
- crypto-js aes 加解密
- rsa 加解密
参考 API:
- crypto-js
- JSEncrypt
依赖
-
crypto-js:
npm i crypto-js
-
JSEncrypt:
npm i jsencrypt
加密流程
先上图
因项目为后台管理系统,所以这里会有两种业务场景:
- 用户在未登录前是没有鉴权 token 的,需在成功登录并获取 token 后和 encryptKey 一并上传后端,后端才能将 token 与 encryptKey 做绑定。
- 用户已登录成功,页面刷新后将会重新生成 aesKey,这时候需从 cookie 中获取 token 并和 encryptKey 上传后端,后端重新绑定 token 和 encryptKey。
代码
encryption.js 封装
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'
const encryptor = new JSEncrypt()
// 生成 AESKEY
export const aesKey = createAesKey()
export function createAesKey () {
const expect = 16
let str = Math.random().toString(36).substr(2)
while (str.length < expect) {str += Math.random().toString(36).substr(2)
}
str = str.substr(0, 16)
return str
}
/**
* AES 加密
* @param word 待加密字段
* @param keyStr 加密 key
* @returns {string} 返回加密字段
*/
export function aesEncrypt (word, keyStr) {
keyStr = keyStr || aesKey
console.log(keyStr)
const key = CryptoJS.enc.Utf8.parse(keyStr)
let srcs = ''
switch (typeof (word)) {
case 'string':
srcs = CryptoJS.enc.Utf8.parse(word)
break
case 'object':
srcs = CryptoJS.enc.Utf8.parse(JSON.stringify(word))
break
default:
srcs = CryptoJS.enc.Utf8.parse(word.toString())
}
const encrypted = CryptoJS.AES.encrypt(srcs, key, {iv: key, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7})
return encrypted.toString()}
/**
* AES 解密
* @param word 待解密数据
* @param keyStr 解密 key
* @returns {string} 返回解密字符串
*/
export function aesDecrypt (word, keyStr) {
keyStr = keyStr || aesKey
const key = CryptoJS.enc.Utf8.parse(keyStr)
const decrypt = CryptoJS.AES.decrypt(word, key, { iv: key, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7})
return CryptoJS.enc.Utf8.stringify(decrypt).toString()}
/**
* RSA 设置公钥
* @param val 公钥
*/
export function setPublicKey (val) {encryptor.setPublicKey(val)
}
/**
* RSA 加密
* @param data 待加密数据
* @returns {PromiseLike<ArrayBuffer>} 返回加密字符串
*/
export function rsaEncrypt (data) {return encryptor.encrypt(data)
}
总结
AES 加解密涉及到的模式(如 CBC、ECB 等)、偏移量和填充等,请参考文中前言提及的文献和 API
本文仅为解决方案参考,请结合实际业务需求及业务场景自由发挥