美文网首页大前端开发
jsencrypt实现前端RSA非对称加密解密(vue项目)

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

作者: 遇侎粒_duyuqin | 来源:发表于2020-03-26 15:52 被阅读0次

    最近一个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:才疏学浅,如果有考虑不周之处或者有更好的解决方案,欢迎指正探讨!

    相关文章

      网友评论

        本文标题:jsencrypt实现前端RSA非对称加密解密(vue项目)

        本文链接:https://www.haomeiwen.com/subject/dotbkhtx.html