您现在的位置是:首页 > 技术教程 正文

前端使用JSEncrypt对登录密码进行RSA加密解密

admin 阅读: 2024-03-31
后台-插件-广告管理-内容页头部广告(手机)

环境

Vue3、soybean admin: “1.0.0”(native-ui: “2.38.0”)、pnpm: “8.5.3”、jsencrypt: “3.3.2”

使用

后端那边要求使用RSA非对称性加密,查阅了网上的资料,CryptoJS并不支持RSA加密,所以选择JSEncrypt

1. 下载依赖

pnpm安装依赖JSEncrypt

pnmp install jsencrypt --save
  • 1

2. 加密登录密码

后端会给出公钥,用于登录密码的加密,现在我们通过JSEncrypt进行RSA加密

加密密码的方法如下:

function getEncryptedPassword(value: string) { const publicKey = "" let encrypt = new JSEncrypt(); encrypt.setPublicKey(publicKey); let encrypted = encrypt.encrypt(value); return encrypted; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3. 登录失败

输入密码:123456,点击登录,接口报错“用户名或密码不正确”。检查后发现,加密出来的字符串和API文档给的字符串不一样。

JSEncrypt加密

AiSCv0JWI47eEmwfCDdzH9jtHZZo/tREW3QO2JO54rNhHZ8YSOELUdWsMP4wfjKYxEZugXUujjK1xTUeejq/KWYbp9qlyInFA2xheNG4a3a+s6ER9NLrsT9LAvD6YP8JdF8EZDl/zCMlQ5Fdh6FqNKlOtIJuiGNhGoPe48y7N9I=

后端API文档示例

090558eddebdef1dd02fe0a8cd59524d5da249d19084333ab2cb050b66aca9f868145a090b643fd9087e7baf5c967c99104acafb4946e1ec5ed78e29957183e3e9955fd1b981728091435bde75da1f62f83202511a6dfbd625f9cf7942536422ad36f3e742804b6aa11aa27ce13ab4feb7b1d9ea7e2e8d3d876d9a685a2a18a9

一眼就不对劲,但是又不知道怎么能变成后端给出的那种编码。怀疑是JSEncrypt的问题。

尝试用后端给的私钥去解密:

function decryptPassword(encryptedPwd: string) { const privateKey= "" let decrypt = new JSEncrypt(); decrypt.setPublicKey(privateKey); let password = decrypt.decrypt(encryptedPwd); return password; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

解密出来确实也是123456,证明了RSA加密流程其实没有问题的,很神奇。

JSEncrypt文档给出的方法很少很少,不清楚如何转变成正确的编码。找了很多资料,最后发现了一个文章:Hutool配合jsencrypt进行RSA加解密,这个博主看了JSEncrypt源码,加密出来的字符串是Base64,而在解密的时候,会把传进来的Base64转成Hex,再去执行解密方法!

4. 解决问题

根据文章知道了,有种编码叫Hex,兴许后端给的就是Hex,直接用在线网站试了Base64转Hex,尝试了一下,果然就登录成功了!

重新整理加密代码,如下:

function getEncryptedPassword(value: string) { const publicKey = "" let encrypt = new JSEncrypt(); encrypt.setPublicKey(publicKey); let encrypted = encrypt.encrypt(value); // copy form stackoverflow let base64ToHex = (base64: string) => { var raw = atob(base64); var hex = ''; for (var i = 0; i < raw.length; i++) { var _hex = raw.charCodeAt(i).toString(16) hex += (_hex.length == 2 ? _hex : '0' + _hex); } return hex; } // JSEncrypt转成base64了,后端需要的是Hex const hexPassword = base64ToHex(encrypted.toString()); return hexPassword; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

5. 补充知识

对编码、加密解密不熟悉,导致一眼看不出问题,花了很多时间去排查。特别是一直以为Hex是哈希的意思,哈希跟加密也有点关联,一时间混淆了

科普一下

  • Hex,也就是十六进制,也称为Base16
  • 区分Base64:Base64使用一个包含64个字符的字符集,包括大写字母(A-Z)、小写字母(a-z)、数字(0-9)以及"+“和”/“符号。有时,Base64编码还会使用”="作为填充字符,以确保编码后的字符串长度是4的倍数。
  • 区分Base16:Base16(Hexadecimal)使用一个包含16个字符的字符集,包括数字(0-9)和字母(A-F)。Base16编码不使用"+“、”/“或”="字符。
  • 除了Base64、Base16,还有其它编码方式,比如Base32、Base58、ASCII编码、Unicode编码(UTF-8、UTF-16、UTF-32)、URL编码等等

资料来自文心一言,欢迎评论指出问题!


总结

对于这次RSA非对称加密登录密码对接的问题,有两点总结:

  1. 之前加密密码都是用的CryptoJS,直接用盐加密登录就能成功,从来没有想过编码方式的问题
  2. 还有其实网上使用RSA去加密登录密码的不多,用MD5、AES的比较多,这也是花了一些时间排查的原因。

通过本次对接了解到了一些编码方面的知识,下次遇到应该不会那么懵了,希望能帮助到大家!

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索
排行榜