加解密
前端调用接口和后端进行通信的过程,其实是数据传输的过程。
在这个过程中,会有很多意外的情况发生,典型的比如中间人劫持攻击,前段时间都**和吴**的事件就好比典型的中间人劫持攻击。
在传统的 http 请求下,数据都是明文传输的,前后端包括中间人都是所见即所得,这样难以保证数据不会被泄漏。
所以解决的办法是很多程序都是部署了 https 的协议。
那如果没有部署 https 的接口呢?一般都会将比较敏感的数据使用数据加密的方法进行传输。
而且不仅仅是数据传输的阶段,在数据存储上,重要的数据也是加密存储的。相信大家都了解过数据库泄漏等安全问题。
说到加解密,有很多方法。例如 jsencrypt、md5 等等。这篇博客说的 crypto 也是类似的,不同点是 crypto 是 nodeJs 的一个模块,类似 fs。
crypto
crypto 是 node 内置的模块,提供了加密功能,其中包括了用于 OpenSSL 散列、HMAC、加密、解密、签名、以及验证的函数的一整套封装。
在没有使用 crypto 之前,我们的前端用的是 jsencrypt 做加密,后端则用 node-rsa 做解密,公钥和私钥都是通过 node-ras 生成的,代码如下:
constNodeRSA=require('node-rsa')letkey=newNodeRSA({b:1024})key.setOptions({encryptionScheme:'pkcs1'})letpubkey=key.exportKey('public')//生成公钥,发给前端用于数据加密letprivkey=key.exportKey('private')//生成私钥,用于数据解密
解密的代码也很简单:
letkey=newNodeRSA(privkey)key.setOptions({encryptionScheme:'pkcs1'})//encryptData是加密后的数据constencryptData='damkiuh34r09u323rbnavjaf9uerjfqefqqb09023h43ibcae9uoue5bin'consts=encryptData.replace(/\s+/g,'+')constdecryptData=key.decrypt(s,'utf8')
这里前端使用 jsencrypt 对数据加密的逻辑我就略过了。不过 node-rsa 不是 nodeJs 固有的模块,使用前需要提前安装
npminstallnode-rsa
crypto 是 node 的内置模块,因此我后面选择了 crypto 重写了数据加解密的逻辑。
加解密的过程十分简洁:
生成加解密需要的的公钥和私钥
使用公钥对数据加密
使用私钥对数据解密
代码
我们先实现生成公钥和私钥的代码:
const{generateKeyPairSync,publicEncrypt,privateDecrypt}=require('crypto')const{publicKey,privateKey}=generateKeyPairSync('rsa',{modulusLength:1024,publicKeyEncoding:{type:'spki',format:'pem'},privateKeyEncoding:{type:'pkcs8',format:'pem'}});
接下来尝试对一段数据进行加密:
//需要加密的数据constdata="datatocrypto"constpub=publicKey.toString('ascii')//公钥加密过程constencryptData=publicEncrypt(pub,Buffer.from(data)).toString('base64');console.log('encode:',encryptData);
得到加密的结果,是一段 base64 的字符串
encode: Me+2EbDsMVLQHPKR8ZB3K88EDs4jNKuHsAZzMIjY3DCO7JEJGu3Tfkwv0tX4kDMiQvrxyJkR7tlpHQ1f91BrweAK6mkeyeyNQ3XOfsHwIEZJB+iv8IZpKiIlyE1KOGaUsN2Q8MyTRZ86IF+Qj4MwotDggXH/ADAHC0oJB/D5H5s=
然后对加密后的数据进行解密
constpri=privateKey.toString('ascii')//私钥解密constdecryptData=privateDecrypt(pri,Buffer.from(encryptData.toString('base64'),'base64'));console.log('decode:',decryptData.toString());
解密的结果
decode: data to crypto
从上面的代码可以看出加密和解密只需要分别调用publicEncrypt
和privateDecrypt
这两个函数即可,而这两个函数,正是内置模块 crypto 对外抛出的方法。
这样看来,加解密的过程是不是更简单一些呢~
作者:晴天同学