RSA、AES加解密

7 篇文章 0 订阅
5 篇文章 0 订阅

RSA加密和AES加密混用


先说一下RSA与AES加密的区别
RSA
非对称加密,公钥加密,私钥解密,反之亦然。由于需要大数的乘幂求模等算法,运行速度慢,不易于硬件实现。通常私钥长度有512bit,1024bit,2048bit,4096bit,长度越长,越安全,但是生成密钥越慢,加解密也越耗时。既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。

AES
对称加密,密钥最长只有128/192/256个bit,执行速度快,易于硬件实现。由于是对称加密,密钥需要在传输前通讯双方获知。基于以上特点,通常使用RSA来首先传输AES的密钥给对方,然后再使用AES来进行加密通讯。

重点,也是本人在研究加密时范的错误

刚开始以为生成的随机密钥就是128/192/256位,就拿128为例,本人就直接生成了128位的随机数(前端密钥),这样是错的
正确的做法是生成它们的除以8的结果,对应的是16/24/32位,这才是随机数的真正位数即前端密钥,128/192/256实际上是bit为单位的,要除8,谨记

首先附上测试AES加密的在线工具https://www.toolnb.com/tools/aesEnDe.html

一、安装jsencrypt、crypto-js

cnpm install jsencrypt//RSA加密需要的依赖
cnpm install crypto-js//AES加密需要的依赖

二、单独建一个js文件为crytpto.js(文件名随意起)

import $post from '@H';
import CryptoJS from 'crypto-js';
import JsEncrypt from 'jsencrypt';

// 默认的 KEY 与 iv 如果没有给
let KEY = CryptoJS.enc.Utf8.parse("1234567890123456");
let IV = CryptoJS.enc.Utf8.parse('1234567890123456');

/**
 * AES加密 :字符串 key iv  返回base64
 */
export function Encrypt(word, keyStr, ivStr) {
  let key = KEY
  let iv = IV

  if (keyStr) {
    key = CryptoJS.enc.Utf8.parse(keyStr);
    iv = CryptoJS.enc.Utf8.parse(ivStr);
  }
  let srcs = CryptoJS.enc.Utf8.parse(JSON.stringify(word));
  /**
   *   mode: 加密模式, 可取值(CBC, CFB, CTR, CTRGladman, OFB, ECB), 都在 CryptoJS.mode 对象下
   *   padding: 填充方式, 可取值(Pkcs7, AnsiX923, Iso10126, Iso97971, ZeroPadding, NoPadding), 都在 CryptoJS.pad 对象下
   *   iv: 偏移量, mode === ECB 时, 不需要 iv,设置了也没问题
   * 返回的是一个加密对象
   */
  let encrypted = CryptoJS.AES.encrypt(srcs, key, {
    iv: iv,
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  });
  return CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
}

/**
 * AES 解密 :字符串 key iv  返回base64
 *
 */
export function Decrypt(word, keyStr, ivStr) {
  let key = KEY
  let iv = IV

  if (keyStr) {
    key = CryptoJS.enc.Utf8.parse(keyStr);
    iv = CryptoJS.enc.Utf8.parse(ivStr);
  }

  let base64 = CryptoJS.enc.Base64.parse(word);
  let src = CryptoJS.enc.Base64.stringify(base64);
  let decrypt = CryptoJS.AES.decrypt(src, key, {
    iv: iv,
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  });
  let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
  return JSON.parse(decryptedStr.toString(decryptedStr));
}
/**
*AES加密有个规则如下:
*加密时用16位为一组,到最后不到16位的时候是自动补充到16位的,而后台在加密补时的充方式上如果是Pkcs5的话,前端就要用Pkcs7去解密(其它方式没试)
*/


/**
 * 生成随机数(前端密钥)
 */
export function randomWord(randomFlag, min, max) {
  let str = "",
    range = min,
    arr = ['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', '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 (randomFlag) {
    range = Math.round(Math.random() * (max - min)) + min;
  }
  for (let i = 0; i < range; i++) {
    let pos = Math.round(Math.random() * (arr.length - 1));
    str += arr[pos];
  }
  return str;
}

/**
 *RSA加密(用后台公钥加密前端密钥共AES加解密时使用)
 * @param userPublicKey(后台生成密钥时存缓存的依据,方便根据该依据找到所公钥对应的私钥)
 * @returns {Promise<any>}
 * 获取后台给的公钥
 * 将自己生成随机数(前端密钥)加密后传给后台
 *
 */
export function getServiceKey(userPublicKey) {
  return new Promise((resolve, reject) => {
    let url = '';//获取公钥的接口
    let params = {
      userPublicKey: userPublicKey
    };
    $post.post(url, params).then(res => {
      if (res.data.code == 200) {
        let webSecretKey = this.randomWord(false, 16);
        this.$cookieStore.setCookie("webSecretKey", webSecretKey, 1);//存储前端密钥,方法很多,用的时候能获取到就行可以用vuex
        let jse = new this.$jsEncrypt
        jse.setPublicKey(res.data.StrKey)
        let encrypted = jse.encrypt(webSecretKey)//给随机数(前端密钥)加密(rsa加密)
        resolve({encrypted, userPublicKey})
      }
    })
  }).then((res) => {
    let url = '';//将前端密钥传给后台接口
    let params = {
      aesKey: res.encrypted,
      userPublicKey: res.userPublicKey
    };
    $post.post(url, params).then(res => {
      if (res.data.code == 200) {

      }
    })
  })
}

/**
 *
 * @param url(请求接口)
 * @param userPublicKey(后台存缓存的依据,方便根据该依据找到存储的前端密钥后进行AES加解密)
 * @param encryptionParams(加密的参数)
 */
export function decryptData(url, userPublicKey, encryptionParams) {
  return new Promise((resolve, reject) => {
    let webSecretKey = this.$cookieStore.getCookie('webSecretKey');
    let par = encryptionParams;
    let params = {
      userPublicKey: userPublicKey,
      params: this.Encrypt(par, webSecretKey, webSecretKey)
    }
    $post.post(url, params).then(res => {
      if (res.data.code == 200) {
        if (res.data.encryptData !== undefined) {
          let encryptData = this.Decrypt(res.data.encryptData, webSecretKey, webSecretKey);
          res.data.encryptData = encryptData
        }
        resolve(res)
      }
    })
  })
}

三、将上面的方法引入到min.js中

//RSA加密,ESA加密
import JsEncrypt from 'jsencrypt'
Vue.prototype.$jsEncrypt = JsEncrypt
import {Decrypt,Encrypt,getServiceKey,randomWord,decryptData} from '@V/commonFunction/cryptoJS'
Vue.prototype.Decrypt = Decrypt
Vue.prototype.Encrypt = Encrypt
Vue.prototype.getServiceKey = getServiceKey
Vue.prototype.randomWord = randomWord
Vue.prototype.decryptData = decryptData

四、项目中调用

      demo() {
        let url = '';
        let userPublicKey = '';//后台存缓存的key
        let encryptionParams = {};//加密的内容
        this.decryptData(url,userPublicKey,encryptionParams).then( res=>{
          if(res.data.code == 200) {
          
          }
        })
      },

aes、rsa属于国外的加密方式,咱们国内也有对应的加密,加密程度丝毫不亚于国外的有兴趣的同学可以移步到国产sm2,sm3,sm4加解密.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值