依赖

前端: jsencrypt

后端:node-rsa

为什么要使用两个呢?因为很操蛋的是 node-rsa 在前端环境中找不到声明,jsencrypt 在后端环境中找不到声明,互换位置则一点影响没有。。。。。。

流程

场景:登录密码尽心 RSA 加密

前端输入用户名密码,点击登录。

image-20220518133920682

首先发起请求获取公钥,加密后请求登录接口,后端查找对应的私钥进行解密。

image-20220518134038457

问题

前端加密之后,将密文发送至后端,后端解析失败

2022-05-18 13:42:28,281 INFO 96788 [midway:redis] client connect success
Error: Error during decryption (probably incorrect key). Original error: Error: error:04099079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
    at NodeRSA.module.exports.NodeRSA.$$decryptKey (/Users/liuhao/code/open-project/f-live/f-live/node_modules/node-rsa/src/NodeRSA.js:301:19)
......

前端加密过程如果下

function login() {
  loading.value = true;
  // 加密登录
  getPublicKey(loginForm.username)
    .then((key) => {
      const sign = new JSEncrypt();
      sign.setPublicKey(key);
      // TODO md5
      let encode = sign.encrypt(loginForm.password) as string;
      return { username: loginForm.username, password: encode };
    })
    .then(loginByPassword)
    .then((token) => console.log(token))
    .finally(() => {
      loading.value = false;
    });
}

解析代码大致为

// 获取 node-rsa
const NodeRSA: NodeRsa = await ctx.requestContext.getAsync('node-rsa'); // midway 语法
const { username, password } = ctx.request.body;

// 读取私钥进行解码
const privateKey = await redis.get(RSA_PRIVATE_KEY + username);
// 如果没有读取到私钥判定为登陆失败
if (!privateKey) {
  throw new CustomError(LOGIN_FAILED.CODE_3, LOGIN_FAILED.MSG_3);
}
const nodeRSA = new NodeRSA(privateKey, 'pkcs8-private-pem', {
  environment: 'node',
});
try {
  // 解码赋值
  ctx.request.body._password = nodeRSA.decrypt(password, 'utf8');
} catch (error) {
  console.log(error);
  throw new CustomError(LOGIN_FAILED.CODE_2, LOGIN_FAILED.MSG);
}

但是同一对秘钥,在其他工具中是可以正常解密的

拨云见日

经过多方查找,终于发现问题所在

const nodeRSA = new NodeRSA(privateKey, 'pkcs8-private-pem', {
  environment: 'node',
  encryptionScheme: 'pkcs1',
});

只需要将加密方案替换为 pkcs1即可正常解码


前端小白