经验分享 - Node crypto 非对称和对称加密遇到的坑
一、非对称加密
非对称加密就是需要公私钥的加密方式,这种加密安全系数相对较高。
实现步骤:
1、生成公私钥对
使用 openssl
命令生成,或者一些网站也可以生成。
2、进行加密/解密
const crypto = require('crypto'); //私钥加密 let encStr = crypto.privateEncrypt('PRIVATE KEY', Buffer.from('加密字符串', 'utf8')); //公钥解密 let decStr = crypto.publicDecrypt('PUBLIC KEY', Buffer.from(encStr, 'utf8')).toString('utf8');
以上步骤在自己电脑调试没啥问题,但是加密数据在别人电脑解密就有问题了。
我将上面的加密后的数据写入网站 cookie,别人在自己的系统中读取 cookie 进行解密时就报错:
error:0406706C:rsa routines:rsa_ossl_public_decrypt:data greater than mod len
网上搜索了一圈,可能的原因:
- 公私钥有问题;
- 要对数据进行 base64 处理;
- 要对数据进行分块解密;
这个问题至今没有解决,稍后找到原因和解决方案再补充到这里!
二、对称加密
对称加密就是加解密的密码都是同一个,这个安全系数就比较低。
最初的实现方案:
const CryptoJs = require('crypto-js'); //加密数据 let encStr = CryptoJS.AES.encrypt('加密字符串', '密码').toString(); //解密数据 let decStr = CryptoJS.AES.decrypt(encStr, '密码').toString(CryptoJS.enc.Utf8);
以上步骤在自己电脑调试没啥问题,但是加密数据在别人电脑解密就有问题了。
我将上面的加密后的数据写入网站 cookie,别人在自己的系统中读取 cookie 进行解密时就报错:
Malformed UTF-8 data
Error: Malformed UTF-8 data
对于这个错误的原因是(参考: 这里 ):des 解密时,如果加密数据不是 8 的整数倍就会报上述错误
解决办法:将数据加密后,再进行 base64 进行加密,解密时首先通过 base64 进行解密,然后再进行 des 解密。即可解决上述问题。
原因找到了,于是尝试解决方案(参考: 这里 ):
const CryptoJs = require('crypto-js'); //加密数据 let encStr = CryptoJS.AES.encrypt('加密字符串', '密码').toString(); //对加密数据进行 base64 处理 //原理:就是先将字符串转换为 utf8 字符数组,再转换为 base64 数据 encInfo = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(encInfo)); //将数据先 base64 还原,再转为 utf8 数据 let data = CryptoJS.enc.Base64.parse(encInfo).toString(CryptoJS.enc.Utf8); //解密数据 let decStr = CryptoJS.AES.decrypt(data, '密码').toString(CryptoJS.enc.Utf8);
以上步骤在自己电脑调试没啥问题,但是加密数据在别人电脑解密就有问题了。
我将上面的加密后的数据写入网站 cookie,别人在自己的系统中读取 cookie 进行解密时还是报错。
最终的解决方案(使用 Buffer
获取并转换 base64 数据):
const CryptoJs = require('crypto-js'); //加密数据 let encStr = CryptoJS.AES.encrypt('加密字符串', '密码').toString(); //对加密数据进行 base64 处理 //原理:就是先将字符串转换为 utf8 字符数组,再转换为 base64 数据 encInfo = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(encInfo)); //将数据先 base64 还原,再转为 utf8 数据 //这里使用 Buffer.from 替代 CryptoJs 的方法 //CryptoJS.enc.Base64.parse(encInfo).toString(CryptoJS.enc.Utf8) let data = Buffer.from(encInfo, 'base64').toString('utf8'); //解密数据 let decStr = CryptoJS.AES.decrypt(data, '密码').toString(CryptoJS.enc.Utf8);
由于都是 Node 中对数据进行加解密,所以安全风险还没那么高,只需要密码不对外泄露就好。所以,目前系统中采用的方案是这种对称加密的方案,如果第 1 种非对称的解决了,再更换。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论