依赖
前端: jsencrypt
后端:node-rsa
为什么要使用两个呢?因为很操蛋的是 node-rsa 在前端环境中找不到声明,jsencrypt 在后端环境中找不到声明,互换位置则一点影响没有。。。。。。
流程
场景:登录密码尽心 RSA 加密
前端输入用户名密码,点击登录。
首先发起请求获取公钥,加密后请求登录接口,后端查找对应的私钥进行解密。
问题
前端加密之后,将密文发送至后端,后端解析失败
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
即可正常解码