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);
会出现的问题:
-
如果上面都没问题就可能会出现报错,没有window,这个和JSEncrypt依赖有关,需要要依赖文件找到
jsencrypt/bin/jsencrypt.js
,在开头加上global.window = this;使this指向window。还是有问题的话直接安装并使用
const JSEncrypt = require("jsencrypt-node");
-
网上说明的在后端使用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会给你一些修改格式的方法,但是踩坑。
注意
网上都是告诉你某一种方法用于加密解密,可以直接像上面一样在前后端都使用同一个方法加密解密。