保姆级教程

您所在的位置:网站首页 下列能够对文件进行加密的格式是 保姆级教程

保姆级教程

2024-07-16 10:43| 来源: 网络整理| 查看: 265

1. 项目背景(需求)

为了保证数据传输的安全性,利用AES+RSA混合加密,配合后端实现数据交互加密

项目环境:vue + axios

2. 实现过程(代码)

AES对称加密我们采用 CryptoJS,AES加密支持AES-128、AES-192和AES-256 (AES传送门)

RSA非对称加密我们采用JSEncrypt,(RSA传送门)

第一步:npm安装两个库

npm i crypto-js jsencrypt

第二步:新建encrypt.js,封装需要用的方法

import CryptoJS from 'crypto-js' import { JSEncrypt } from 'jsencrypt' /** * 递归自然排序: key + value * sortObjFunc: 排序方法 * isArraysFunc: 判断是否array * isObjectFunc: 判断是否object * isHasValues: 判断空值,null,undefined * 排序前: {"aaa":"111","bbb":"222","list_1":[],"list":["3","13"],"map":{"b":"2","c":"3"}} * 排序后: aaa111bbb222list423.852313list_1mapb2c3 */ export const signUtil = { sortObjFunc: function (plaintext) { let signStr = '' let keyList = [] for (const key in plaintext) { keyList.push(key) } if (keyList.length) { keyList.sort() } const len = keyList.length for (let i= 0; i < len; i++) { let value = plaintext[keyList[i]] if (value && signUtil.isHasValues(value)) { if (signUtil.isArraysFunc(value) || signUtil.isObjectFunc(value)) { value = signUtil.sortObjFunc(value) } } // 数组取value,否则取key+value(排除null,空,undefined) if (signUtil.isArraysFunc(plaintext)) { signStr += value } else { value !== null ? signStr += keyList[i] + value : signStr += keyList[i] } } return signStr }, isArraysFunc (item) { return Object.prototype.toString.call(item) === '[object Array]' }, isObjectFunc (item) { return Object.prototype.toString.call(item) === '[object Object]' }, isHasValues (item) { return item !== 'null' || item !== 'undefined' || item !== 0 } } /** * aes加密 * genKey: 获取key * encrypt: AES加密 * decrypt: AES解密 */ export const aesUtil = { genKey: function(expect = 16) { const random = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' let str = '' while (str.length < expect) { str += random.charAt(Math.random() * random.length) } return str }, encrypt: function(plaintext, key) { if (plaintext instanceof Object) { plaintext = JSON.stringify(plaintext) } let encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(plaintext), CryptoJS.enc.Utf8.parse(key), { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }) return encrypted.toString() }, decrypt: function(ciphertext, key) { let decrypt = CryptoJS.AES.decrypt(ciphertext, CryptoJS.enc.Utf8.parse(key), { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }) let decString = CryptoJS.enc.Utf8.stringify(decrypt).toString() if (decString.charAt(0) === '{' || decString.charAt(0) === '[') { decString = JSON.parse(decString) } return decString } } /** * rsa加密 * encrypt: 公钥加密 * decrypt: 私钥解密 * ensign: rsa签名 * design: rsa验签 */ const encryptor = new JSEncrypt({ default_key_size: 1024 }) export const rsaUtil = { encrypt: function (key, publicKey) { publicKey && encryptor.setPublicKey(publicKey) return encryptor.encrypt(key) }, decrypt: function (key, privateKey) { privateKey && encryptor.setPrivateKey(privateKey) return encryptor.decrypt(key) }, ensign: function (data, privateKey){ privateKey && encryptor.setPrivateKey(privateKey) return encryptor.sign(data, CryptoJS.SHA256, 'sha256') }, design: function (data, signature, publicKey){ if (signature && publicKey) { encryptor.setPrivateKey(publicKey) return encryptor.verify(data, signature, CryptoJS.SHA256) } } } /** * RSA秘钥对 * publicKey: 前端rsa公钥 * privateKey: 前端rsa私钥 * servePublicKey: 服务端rsa公钥 */ export const publicKey = encryptor.getPublicKey() export const privateKey = encryptor.getPrivateKey() export const servePublicKey = '服务端公钥'

第三步:改造Axios

import axios from 'axios' import { signUtil, aesUtil, rsaUtil, servePublicKey, privateKey } from 'encryptn' axios.defaults.timeout = 20000; axios.defaults.baseURL = 'http://8.8.8.8:8080' axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'; axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*'; // 请求拦截器 axios.interceptors.request.use((config) => { // other code here... if (config.data) { // 生成签名 const signKey = signUtil(config.data) const newSignKey = rsaUtil.ensign(signKey, privateKey) // AES随机秘钥 const romkey = aesUtil.genKey() // 服务端公钥对随机秘加密 const aesKey = rsaUtil.encrypt(romkey, servePublicKey) // AES + 随机秘对data体加密 config.data['sign'] = newSignKey const aesData = aesUtil.encrypt(config.data, romkey) const newData = { data: aesData, key: aesKey } config.data = newData } return config; }, (error) => { return Promise.reject(error); }); // 响应拦截器 axios.interceptors.response.use((res) => { // other code here const { data, key } = res.data // 客户端私钥解密key const rsaKey = rsaUtil.decrypt(key, privateKey) // AES + key解密data const newData = aesUtil.decrypt(data, rsaKey) // 重新生成签名验证 if (newData.sign) { const copyData = JSON.parse(JSON.stringify(newData)) delete copyData.sign const data = signUtil(copyData) const flag = rsaUtil.design(data, newData.sign, servePublicKey) if (!flag) { return Promise.reject({ message: '签名失败' }) } return Promise.resolve(res.data) } else { return Promise.reject({ message: '请求异常' }) } }, (error) => { return Promise.reject(error); });

## 3. 注意问题

签名排序统一,需要和后端签名一致才可以通过加密长度统一,这里统一使用1024,具体前后端协商数据结构统一,返回体的数据结构一致,方便后面验证签名前端加密一定程度增加了网络攻击的难度,最好还是上https



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3