JAVA-WEB项目中,前后台结合AES和RSA对数据加密处理

实际项目中为了系统安全,我们经常需要对请求数据和响应数据做加密处理,这里以spring后台,vue前台的java web为例,记录一个实现过程

一、为什么要结合AES和RSA?

因为AES是对称加密,即加密解密用的秘钥是一样,这样一来AES的秘钥保管尤其重要,但是AES有个很好的优点,就是处理效率高。而RSA是不对称加密,即加密解密用的秘钥不一样,分别叫公钥和私钥,通常用公钥加密,然后用私钥解密,其中公钥可以公开,只需要保管好私钥即可,而相比AES而言RSA速度慢效率低。所以,通常我们结合这两种加密方式的优点来完成数据的安全传输。

二、AES和RSA的结合使用过程

1.前端随机动态生成aesKey:因为AES的加密解密秘钥需要一致,如果整个系统写死AES的秘钥会很不安全,所以每次请求动态生成aesKey会比较好

2.前端用RSA对动态aesKey加密:动态aesKey需要传到后端供解密,传输过程用RSA加密

3.前端保存动态aesKey:因为同一个请求的响应需要一样的aesKey解密,所以前端还得把动态aesKey保存下来,可以再随机生成一个id,然后按键值对的方式保存在前端变量中{id: aesKey}

4.把加密的aesKey和id放到请求头

5.后端用RSA私钥解密得明文aesKey:后端从请求头取出加密的aesKey,然后用私钥解密拿到明文的aesKey,然后对请求数据解密

6.后端用明文aesKey加密响应数据

7.后端把请求过来的id放到响应头

8.前端根据响应头的id,取到对应的aesKey,对响应数据解密

9.前端删除动态的aesKey

三、具体实现案例

1.前端实现AES和RSA的公共方法

        aesUtils.js:


 const CryptoJS = require('crypto-js')

 function GetRandomNum (n) {
    let 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(n == null) {
      n = 16
    }
    let res = ""
    for(let i = 0; i < n ; i++) {
      let id = Math.ceil(Math.random()*46)
      res += chars[id]
    }
    return res
 }

function GetUuid () {
  let s = []
  const hexDigits = '0123456789abcdef'
  for (let i = 0; i < 36; i++) {
    let indexStart = Math.floor(Math.random() * 0x10)
    s[i] = hexDigits.substring(indexStart, indexStart+1)
  }
  s[14] = '4'
  let indexStart = (s[19] & 0x3) | 0x8
  s[19] = hexDigits.substring(indexStart, indexStart+1)
  s[8] = s[13] = s[18] = s[23] = '-'
  return s.join('')
}

function Decrypt (word, key, iv) {
  let key = CryptoJS.enc.Utf8.parse(key)
  let base64 = CryptoJS.enc.Base64.parse(word)
  let src = CryptoJS.enc.Base64.stringify(base64)
  var decrypt = CryptoJS.AES.decrypt(src, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding })
  var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
  return decryptedStr.toString()
}

function Encrypt (word, key, iv) {
  let key = CryptoJS.enc.Utf8.parse(key)
  let src = CryptoJS.enc.Utf8.parse(word)
  var encrypted = CryptoJS.AES.encrypt(src, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding })
  return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
}

export default {
  Decrypt,
  Encrypt,
  GetRandomNum,
  GetUuid,
}

        rsaUtils.js:

import JSEncrypt from 'jsencrypt'

const pubKey = `MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMYWwlqtkWIdA0I/54TP/k1VLgyNwzQB1IvrVKdNfobivHzN02VFGAED1hDSLDiSp4yYrFcXmMFReJJOJ1zjvWECAwEAAQ==`

const encrypt = new JSEncrypt()
encrypt.setPublicKey(pubKey)

function Encrypt(str) {
	let data = encrypt.encrypt(str.toString())
	return data
}

function Decrypt(str) {
	let data = encrypt.decrypt(str.toString())
	return data
}

export default {
  Encrypt,
  Decrypt,
}

 2.前端在拦截请求处,生成AES随机秘钥并加密请求数据,再用RSA加密AES秘钥并放到请求头
        fetch.js:

const aesKeys = {}

instance.interceptors.request.use(function(request) {
	let randomKey = aes.GetRandomNum()

	let reqData
	if (request.data instanceof Object) {
		reqData = JSON.stringify(request.data)
	} else {
		reqData = request.data
	}

	request.data = aes.Encrypt(reqData, randomKey, randomKey)

	let uuid = aes.GetUuid()
	let encryptAesKey = rsa.Encrypt(randomKey)
	request.headers['Encrypt
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值