前言
 最近在工作中使用到了RSA和AES加密,网上也有很多教程,但是没有什么时效性了,所以想把内容记录下来和同学们一起学习交流
一、为什么要使用RSA和AES?
- 
RSA和AES是什么? - 
RSA:非对称加密,使用 公钥和私钥加密和解密,加密速度慢
- 
AES:对称加密,加密和解密使用 同一个密钥,加密速度快
 
- 
- 
为什么要混淆?只用一个不行吗? 因为AES加密速度快,自然是我们的第一选择,但是缺点也明显。因为使用 同一个密钥,如果有一方密钥泄露,那么数据也就不安全了。所以我们可以结合RSA互补二者的缺点,使用RSA来加密传递AES密钥,用AES来加密数据。
二、思路
- 服务端生成RSA密钥对(privateKey-1、publicKey-1),把公钥 publicKey-1发送给客户端
- 客户端生成RSA密钥对(privateKey-2、publicKey-2),使用服务端的公钥加密自己的公钥publicKey-2,将加密后的数据发送给服务端
- 服务端使用自己的私钥解密获取到客户端的公钥,将AESKey使用客户端公钥 publicKey-2加密发送给客户端
- 客户端使用自己的私钥解密获取AESkey
- 双方使用AESkey来进行数据传输
流程图
如果流程从客户端开始,原理也是一样的,只需要把双方角色互换即可
三、代码
前端需要用到两个npm包
- crypto-js 用于操作AES密钥
- JSEncrypt 用于操作RSA密钥,如果加密密文过长可以替换为encryptlong
生成RSA密钥
import CryptoJS from 'crypto-js/crypto-js'
import JSEncrypt from 'jsencrypt'
// 初始化
const keyPair = new JSEncrypt()
const genKeyPair = () => {
    const genKeyPair = {}   
    genKeyPair.privateKey = rsaUtil.keyPair.getPrivateKey() // 生成RSA密钥
    genKeyPair.publicKey = rsaUtil.keyPair.getPublicKey() // 生成RSA公钥
    return genKeyPair
}
复制代码RSA公钥加密 – 收到服务端公钥后加密公钥
/**
 * rsa公钥加密
 * @param {*} cipherContent 需要加密内容
 * @param {*} publicKey 服务端的公钥
 * @returns
 */
const encryptByRsa = (cipherContent, publicKey) => {
    const newValue = typeof cipherContent === 'string' ? cipherContent : cipherContent.toString()
    keyPair.setPublicKey(publicKey)
    return keyPair.encryptLong(newValue) // 注意:加密类型为string
},
复制代码RSA解密 – 解密后取到AES key
/**
 * rsa私钥解密
 * @param {*} plainContent 解密的内容
 * @param {*} privateKey 解密私钥
 * @returns
 */
const decryptByRsa = (plainContent, privateKey) => {
    keyPair.setPrivateKey(privateKey)
    return keyPair.decryptLong(plainContent)
},
复制代码AES 加密
/**
 * AES 加密
 * @param {*} cipherContent 加密的内容
 * @param {*} key AES key
 * @returns
 */
const encrypt = (cipherContent, key) => {
    const aesKey = CryptoJS.enc.Utf8.parse(key)
	const newValue = typeof cipherContent === 'string' ? cipherContent : cipherContent.toString()    
    const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(newValue), aesKey, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
    return encrypted.toString()
}
复制代码AES 解密
/**
 * AES解密
 * @param {*} plainContent 解密的内容
 * @param {*} key AES key
 * @returns
 */
decrypt: (plainContent, key) => {
    const aesKey = CryptoJS.enc.Utf8.parse(key)
    const decrypt = CryptoJS.AES.decrypt(plainContent, aesKey, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
    const decString = CryptoJS.enc.Utf8.stringify(decrypt).toString()
    return decString instanceof Object ? decString : JSON.parse(decString)
},
复制代码四、Q&A
剩下几个问题想和大家一起探讨下
- 
前端加密有意义吗? 我的回答是防君子不防小人,真正的”安全”还是得靠后端的同学 
- 
前端怎么安全的存储密钥? 我现在的操作还是二次加密后存储session,不知道同学们是否有更好的方案 
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
    























![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)
