在数据传输过程当中,可能存在数据被窃取的安全隐患(主要http)。 对于安全需求较高的项目而言,加密是保证数据安全的最直接的方式。前端
常见加密方式分为如下两类:node
Tips:ios
MD五、SHA256等通常称为数据摘要算法(采用哈希算法),即将数据块映射为定长的摘要信息,过程是单向的(没法反推原数据),通常用于数据验签(校验数据是否完整或校验数据是否被篡改)。算法
以中后台管理项目为例:数据库
需完善点:npm
设想: 鉴于AES较高的性能及RSA公私钥方式的易用性,可否结合这二者的优势实现对数据安全的保障?element-ui
如下是构思的业务流程:axios
这里结合Vue实现 Tip:后端
// 预登陆 获取后台公钥
preLogin (formName) {
// 校验 预登陆表单(此处为element-ui,其余ui框架相似)
this.$refs[formName].validate(async (valid) => {
if (valid) {
const res = await adminPreLogin({
name: this.form.username, // 用户名
verifyCode: this.form.verificationCode, // 验证码(经过get请求+tag参数获取验证码图片)
tag: this.uuid // 获取验证码时的tag(可以使用uuid或时间戳+随机数等方式生成)
})
if (res.data.res === 0) {
// 正式登陆 传入后台返回的公钥及后台生成这次预登陆的preSessionId
// 正式登陆后,后台可根据此preSessionId查找对应的RSA私钥进行解密
// 同一时间内可能存在多人同时登陆帐号(引入preSessionId解决)
this.login(res.data.publicKey, res.data.preSessionId)
} else {
// 预登陆失败,则刷新验证码,重置验证码输入框
this.uuid = uuidv4()
this.$set(this.form, 'verificationCode', '')
}
}
})
}
复制代码
async login (publicKey, preSessionId) {
// 随机生成 构成key iv的字符串(这里都采用AES密钥长度16位)
let keyString = randomGenerate(16) // 这里使用工具类随机生成(详细实现见下文)
let ivString = randomGenerate(16)
// 生成AES 密钥和向量
let key = CryptoJS.enc.Utf8.parse(keyString) // AES密钥
let iv = CryptoJS.enc.Utf8.parse(ivString) // AES向量
// RSA公钥加密
let pubKey = new NodeRSA(publicKey)
pubKey.setOptions({ encryptionScheme: 'pkcs1' }) // 设置填充方式,前、后端保持统一便可
// 这里拆分出
let pwd = CryptoJS.AES.encrypt(
this.form.password, // 加密原文
key, // AES密钥
{
iv: iv, // AES向量
mode: CryptoJS.mode.CBC, // 指定CBC模式
padding: CryptoJS.pad.Pkcs7 // 指定pkcs7填充模式
})
// 发送正式登陆请求
const res = await adminLogin({
name: this.form.username,
password: pwd,
authKey: pubKey.encrypt(keyString, 'base64'), // 加密后base64编码
authIv: pubKey.encrypt(ivString, 'base64'),
preSessionId: preSessionId // 预登陆返回的preSessionId
})
if (res.data.res === 0) {
// 验证成功后,可存储AES密钥和向量,后续请求关键信息使用AES加密后上传便可
sessionStorage.setItem('aesKey', keyString)
sessionStorage.setItem('aesIv', ivString)
this.$router.push({ name: 'xxx-home' }) // 进入管理主页面
// 还能够存储token、session等信息,并提示用户登陆成功 这里不作展现
} else {
// 正式登陆失败,则刷新验证码,重置验证码输入框
this.uuid = uuidv4()
this.$set(this.form, 'verificationCode', '')
}
}
复制代码
// 生成随机字符串
function randomGenerate (length) {
const chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
if (!Number.isInteger(length) || length <= 0) { // 合法性校验
console.error('请检查输入随机字符串长度是否为正整数!')
return 'Error'
}
let randomString = ''
for (let i = 0; i < length; i++) {
randomString += chars[Math.floor(Math.random() * chars.length)]
}
return randomString
}
export { randomGenerate }
复制代码
理解AES + RSA的结合加密思路后,实现方式可根据具体状况修改。 结合两种加密方式使用,能够知足大多数的使用场景,发挥出各自的优势。安全
————加密定义及分类摘自百度百科
欢迎你们积极讨论,共同进步。 个人简书