最近项目登录需要加密,用的是AES和RSA组合加密,公钥加密密钥,密钥加密数据,将这两个参数传给后端,后端再用私钥解密出密钥,然后密钥解密出数据。
本来用的RSA/ECB/PKCS1Padding规范,demo都调通了。放到项目中后端java有漏洞,只能改成RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING这种规范,后端只改个名字就ok。前端得改用node-forge插件才行。
后端自己搜有几篇,我在这放一下前端vue的
需要安装npm install jsrsasign --save,npm install crypto-js --save,npm install node-forge --save
utils下新建encryption.js文件:
import jsCookie from 'js-cookie' // 导入 cookie
import jsrsasign from 'jsrsasign' // 导入 生成公钥密钥 插件
import CryptoJS from 'crypto-js' // 导入 AES 插件
import forge from 'node-forge'
// 公钥加密密钥 的方法
function pubencrypt(aeskey, pubencryptKey) {
const publicKeyAll = '-----BEGIN PUBLIC KEY-----\n' + pubencryptKey + '\n-----END PUBLIC KEY-----'
var publicKey = forge.pki.publicKeyFromPem(publicKeyAll)
var buffer = forge.util.createBuffer(aeskey, 'utf8')
var bytes = buffer.getBytes()
var pubencryptedText = forge.util.encode64(publicKey.encrypt(bytes, 'RSA-OAEP', {
md: forge.md.sha256.create(),
mgf1: {
md: forge.md.sha1.create()
}
}))
return pubencryptedText
}
// 生成 公钥和私钥 的方法
export function jsrsasignFn() {
var rsaKeypair = jsrsasign.KEYUTIL.generateKeypair('RSA', 1024)
var private1 = jsrsasign.KEYUTIL.getPEM(rsaKeypair.prvKeyObj, 'PKCS1PRV')
var public1 = jsrsasign.KEYUTIL.getPEM(rsaKeypair.pubKeyObj)
var rsaKey = {
'privateKey': private1.substring(31, private1.length - 31).replace(/\r\n/g, ''),
'publicKey': public1.substring(28, public1.length - 28).replace(/\r\n/g, '')
}
return rsaKey
}
// AES 加密 data:要加密解密的数据,AES_KEY:密钥,IV:偏移量
function encrypt(data, AES_KEY, IV) {
const key = CryptoJS.enc.Utf8.parse(AES_KEY)
const iv = CryptoJS.enc.Utf8.parse(IV)
const encrypted = CryptoJS.AES.encrypt(data, key, {
iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
return encrypted.toString()
}
// 生成16位随机数
function getmm(num = 16) {
var amm = ['!', '@', '#', '$', '%', '&', '*', '(', ')', '_', 1, 2, 3, 4, 5, 6, 7, 8, 9]
var tmp = Math.floor(Math.random() * num)
var s = tmp
s = s + amm[tmp]
for (let i = 0; i < Math.floor(num / 2) - 1; i++) {
tmp = Math.floor(Math.random() * 26)
s = s + String.fromCharCode(65 + tmp)
}
for (let i = 0; i < (num - Math.floor(num / 2) - 1); i++) {
tmp = Math.floor(Math.random() * 26)
s = s + String.fromCharCode(97 + tmp)
}
return s
}
// 参数加密 的方法
export function resEncryption(data, publicKey) {
// 生成随机密钥(key+iv)
var key = getmm()
var iv = getmm()
// 密钥 加密 数据(将json转成字符串再进行加密)
var newStr = encrypt(JSON.stringify(data), key, iv)
// 公钥 加密 密钥(key+iv组成)
var appSecret = pubencrypt(key + iv, jsCookie.get('publicKey'))
// 返回数据
var formData = new URLSearchParams()
formData.append('encryptedData', newStr)
formData.append('appSecret', appSecret)
return formData
}
页面中使用
import { resEncryption } from '@/utils/encryption.js'
sendDataFn() {
const encData = {
phoneNumber: '123',
token: 'abc'
}
getSendCode(resEncryption(encData),
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(res => {
if (res.code === 1000) {
this.$message({
message: '成功!',
type: 'success'
})
}
}).catch(err => {
console.log(err)
})
}