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

环境

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

2. 加密登录密码

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

加密密码的方法如下:

function getEncryptedPassword(value: string) {
  const publicKey = ""
  let encrypt = new JSEncrypt();
  encrypt.setPublicKey(publicKey);
  let encrypted = encrypt.encrypt(value);
  return encrypted;
}

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;
}

解密出来确实也是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;
}

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的比较多,这也是花了一些时间排查的原因。

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

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值