大前端开发

jsencrypt实现前端RSA非对称加密解密(vue项目)

2020-03-26  本文已影响0人  遇侎粒_duyuqin

最近一个vue项目要求所有密码数据需要使用RSA非对称加密传输,以为挺简单,结果开发过程中还是遇到了些问题,简单做个笔记。同时也希望可以帮助到遇到同样问题的道友门。

概念

实现—生成密钥

重点来了:使用jsencrypt实现RSA非对称加解密
因为这里直接在前端加解密,所以需要一对现成的密钥,我们通过密钥在线生成器得到:

密钥 密钥有了,该上代码了
首先安装jsencrypt依赖包
npm install jsencrypt

然后在需要使用的文件中引入JSEncrypt,我是将所有工具函数都封装在一个js文件的,我就直接在该文件中引入,我看也有人是在main.js中引入的。

import { JSEncrypt } from 'jsencrypt' 
// 或者下面这种方式引入
// import JSEncrypt from 'jsencrypt/bin/jsencrypt'

实现—加密

/**
 * RSA非对称加密
 * @param data 需要加密的数据
 */
export function rsaEncrypt(data) {
  // 公钥,,复制前面生成的公钥
  const PUBLIC_KEY = `MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLCf1tQoxpXg6FQPZnCmUpZLvN
  IjXRjtFmsQ8LEarKnamjnwAhDnHOpz4pCWXHFcox40FhJQzUmyAzKgIluALvbjYl
  HamB1IY+XBeEsR/h2BiRufwSWj1YV4r1rIbhd5p+ymqEZcQeWpcY4ueke+k98RZ0
  +VBOuf4DGTdrb8L/PwIDAQAB`
  // 使用公钥加密
  const encrypt = new JSEncrypt()
  encrypt.setPublicKey(PUBLIC_KEY)
  let result = encrypt.encrypt(data)
  return result
}

实现—解密

/**
 * RSA 解密
 * @param data 需要解密的数据
 */
export function rsaDecrypt(data) {
  //私钥,复制对应的私钥用于解密
  const PRIVATE_KEY = `MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAMsJ/W1CjGleDoVA
  9mcKZSlku80iNdGO0WaxDwsRqsqdqaOfACEOcc6nPikJZccVyjHjQWElDNSbIDMq
  AiW4Au9uNiUdqYHUhj5cF4SxH+HYGJG5/BJaPVhXivWshuF3mn7KaoRlxB5alxji
  56R76T3xFnT5UE65/gMZN2tvwv8/AgMBAAECgYBeFe4C0GDCftxZsWW9D9sa2FwS
  TbUEu5qbbJbc+T3ckDzI3mgv6UKhkWxDleA85gMBJR7pxkJwzsWYD/JYyjFJMJRm
  5T7muGxm9CnywUH4dng+IlJc+JtqNOGVF9QmCfA5dI+WQu7xqoBAh3GI5vEEHJMo
  qYaDSGboYHSd+y5eYQJBAO6aITksboR7TflI6zwDtGmef5xq6DmcdEUtVGe+Bpx3
  HOIABKIqnf3znTVe9MYkk95fXlDJlgPTmjDlo8TvxVECQQDZ2AWZKbcFqrpucv7B
  O2uLwWfh5daBbmpt7ixhNRNrEFYopCJTUKFm/9Rk4NUQ89HBQdjSMUnlaYhqGjVB
  IZePAj8UgSpZv3e/6tjIk3ujrK3UZcqRpp5OVSOozjxyreHjkFjrExVS2la5fDYG
  YCKo5HvQoGF6j9hUe9rEWPe59OECQHwjL72CGfuuuKJsAWRX2gc/5VTDRqNnKlsO
  mFekiTY/jvmF3tGfZvps2rnJrWEFsAfy3/2XfMawhr3/xU0iOV0CQQC74OOHYKhm
  C6rvN+Kzk63OrUmC8F/a9xmLSSG8Jd0gmHGkmRMeYxRUxgs+LS/htHDAKYyGH2uD
  msqCj47HstQs`
  //使用私钥解密
  const decrypt = new JSEncrypt()
  decrypt.setPrivateKey(PRIVATE_KEY)
  let result = decrypt.decrypt(data)
  return result
}

实现—测试

到这里我们的加密解密方法就完成了,在需要的地方直接拿过来用就好了!

import { rsaEncrypt, rsaDecrypt } from '@/utils'

// 在需要的地方使用
console.log('加密:', rsaEncrypt('123456'))
console.log('解密:', rsaDecrypt (rsaEncrypt('123456')))
执行效果如下: 测试

大功告成!这样就完了?我以为这样就ok了。

然而!!!当我重新启动项目的时候报错了。。报错了。。。 引入JSEncrypt报错

实现—解决bug

当然,如果没有遇到这个bug,就可以忽略下面的内容了。
从上面截图可以看到,重启项目的时候报错:navigator is not defined
而且这个bug有点奇葩,先启动项目再引入jsencrypt就什么问题都没有,但是先引入jsencrypt再启动项目就报错。这也是我前面能顺利执行的原因所在。
通过好一通折腾,用了网上的各种方法,比如在main.js引入jsencrypt、引入jsdom之类的,都没能解决这个问题,最终还是在jsencrypt的git相关issue下找到了这个问题的解决方案。

解决方案
翻译下,用这里的jsencrypt替换node_modules/jsencrypt/bin 文件夹中的jsencrypt.js的。所以是修改了源码,我将这个文件下载下来,里面是一个jsencrypt.js文件,替换掉原本的jsencrypt.js,问题解决了。
附上链接:jsencrypt.zip
对比了一下两个文件,发现是删掉了navigator相关的内容,对比图:
对比图1 对比图2 对比图3 对比图4

实现—更换实现方式

到这里问题就算基本解决了,但是由于项目组不止我一个前端,我不能要求每个同事或者以后接手维护项目的同事都要在node_modules中去替换文件。
所以就采用了另外一种方案:将jsencrypt.js通过在线js压缩器压缩至jsencrypt.min.js中,然后把jsencrypt.min.js放到src/assets/jsencrypt文件夹中,就不用npm install的方式了。
换了种方式,jsencrypt的引用方式需要做出相应的调整:

// 引用JSEncrypt
import JSEncrypt from '../assets/jsencrypt/jsencrypt.min.js'

参考链接:RSA非对称加密传输---前端加密&解密(VUE项目)
https://github.com/travist/jsencrypt/issues/144
PS:才疏学浅,如果有考虑不周之处或者有更好的解决方案,欢迎指正探讨!

上一篇下一篇

猜你喜欢

热点阅读