nodejs使用RSA,jsencrypt前端加密解密

28 阅读3分钟

RSA

RSA作为一种算法广泛使用,需要一对公钥和私钥。 公钥可以公布给任何人,数据通过公钥进行加密。只有拥有私钥的人才可以破解该数据。私钥必须相当保密。

要在node中使用RSA很简单,npm提供了一个RSA的包,npm install node-rsa就可以安装包。

引入该包后可以const key = new NodeRSA({b: 512});指定密钥的格式,包括1024,2048等等。

使用node-rsa加密解密很简单,按照以下方法即可实现加密解密。不过要注意格式。

const encrypted = key.encrypt(text, 'base64');
console.log('encrypted: ', encrypted);
const decrypted = key.decrypt(encrypted, 'utf8');
console.log('decrypted: ', decrypted);

生成公钥私钥也很简单,你可以这样生成默认为‘PEM’格式的公钥和私钥

const public = key.exportKey('public')
const private = key.exportKey('private')

当然,你还可以指定生成‘der’格式的字符串

const public = key.exportKey('pkcs8-public-der')
const private = key.exportKey('pkcs1-der')

前面的介绍就到这里,对于RSA还是不过多介绍。

实际加密

openSSL生成RSA密钥,可以直接搜索可以在vscode跑的命令,在某个文件夹下去跑命令生成私钥和公钥。

由于npm官方文档与gbt的回答产生分歧就不过多操作,直接跑命令生成公私钥方便。

前端jsencrypt加密

前端我在网上搜到的绝大部分都是使用jsencrypt进行加密,但是很多文章其实介绍的都只是加密解密的方法,并没有实际应用到前后端进行数据传输。

我在这里通过jsencrypt拿到公钥进行加密,这里的data使用的是JSON字符串。jsencrypt.encrypt方法只能接受字符串。

export function getJsencrypt(data:string) {
  const jsencrypt = new JSEncrypt();
  jsencrypt.setPublicKey(publicKey);//设置公钥用于加密,默认pem格式
  const rsaPassword = jsencrypt.encrypt(data);
  return rsaPassword;
}

通过这个方法拿到加密后的字符串后,进行post请求将数据发送: const pw = getJsencrypt(JSON.stringify(data)); const res = await axios.post("login", { password: pw });

后端重新实例化一个新的对象用于解密:

const decrypt = new JSEncrypt();
decrypt.setPrivateKey(data); //设置秘钥
const uncrypted = decrypt.decrypt(password);

会出现的问题:

  1. 如果上面都没问题就可能会出现报错,没有window,这个和JSEncrypt依赖有关,需要要依赖文件找到jsencrypt/bin/jsencrypt.js,在开头加上global.window = this;使this指向window。

    还是有问题的话直接安装并使用const JSEncrypt = require("jsencrypt-node");

  2. 网上说明的在后端使用crypto对前端JSEncrypt加密的数据进行解密容易踩坑。 当你这样使用:

// 创建一个用于解密的RSAPrivateKey对象
const rsaPrivateKey = crypto.createPrivateKey({ key: privateKey, format: 'pem' });

// 假设这是从客户端接收的加密数据
const data = '...' // 加密后的数据

// 解密数据
const decryptedData = crypto.privateDecrypt(
    { key: rsaPrivateKey, padding: crypto.constants.RSA_PKCS1_PADDING },
    Buffer.from(data, 'base64')
);

你会发现报错,RSA_PKCS1_PADDING这个格式已经不再支持,因为jsencrypt加密后的内容默认格式就是pkcs1的,你需要使用相同的格式才能解开jsencrypt加密。而jsencrypt并没有直接提供修改格式的方法,有些ai会给你一些修改格式的方法,但是踩坑。

注意

网上都是告诉你某一种方法用于加密解密,可以直接像上面一样在前后端都使用同一个方法加密解密。