阅读 3160

node数据加密,还不快快点进来?

crypto模块

node.js中crypto 模块提供了加密功能,包含对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装。 使用 require('crypto') 来访问该模块。

let cryto = require('crypto');
console.log(cryto.getHashes());
复制代码

cryto模块支持下列数组中的散列哈希算法

[ 'DSA', 'DSA-SHA', 'DSA-SHA1', 'DSA-SHA1-old', 'RSA-MD4', 'RSA-MD5', 'RSA-MDC2', 'RSA-RIPEMD160', 'RSA-SHA', 'RSA-SHA1', 'RSA-SHA1-2', 'RSA-SHA224', 'RSA-SHA256', 'RSA-SHA384', 'RSA-SHA512', 'dsaEncryption', 'dsaWithSHA', 'dsaWithSHA1', 'dss1', 'ecdsa-with-SHA1', 'md4', 'md4WithRSAEncryption', 'md5', 'md5WithRSAEncryption', 'mdc2', 'mdc2WithRSA', 'ripemd', 'ripemd160', 'ripemd160WithRSA', 'rmd160', 'sha', 'sha1', 'sha1WithRSAEncryption', 'sha224', 'sha224WithRSAEncryption', 'sha256', 'sha256WithRSAEncryption', 'sha384', 'sha384WithRSAEncryption', 'sha512', 'sha512WithRSAEncryption', 'shaWithRSAEncryption', 'ssl2-md5', 'ssl3-md5', 'ssl3-sha1', 'whirlpool' ]

常见的几种算法

1 散列(哈希)算法

  • 特性
    1. 不可逆,不能从输出推算出输入的值
    2. 不管加密内容多长,最后输出的结果长度相等
    3. 内容不同,输出的结果就完全不同,内容相同,则输出的结果相同

例:md5摘要算法

虽然人们经常说md5加密,但实际上,md5属于摘要算法,他是不可逆的,确切的说,他不是加密算法。市面上常见的md5解密网站也并不是真的将md5摘要算法的结果逆向解密出来,而是通过撞库的方式,硬生生装出来的。
复制代码
let md5 = crypto.createHash('md5');
md5.update('123456'); // update数据
let result = md5.digest('hex') // 十六进制输出
console.log(result) // e10adc3949ba59abbe56e057f20f883e
复制代码

在调用digest方法之前,可以多次调用update方法添加数据,但是在调用digest方法之后,无法再继续使用update方法

let md5 = crypto.createHash('md5');
md5.update('123');
md5.update('456');
let result = md5.digest('hex');
console.log(result); // e10adc3949ba59abbe56e057f20f883e
md5.update('789') // Error: Digest already called
复制代码

常见的输出格式还有base64格式

let md5 = crypto.createHash('md5');
md5.update('123456');
let result = md5.digest('base64');
console.log(result) // 4QrcOUm6Wau+VuBX8g+IPg==
复制代码

数据库存的信息如果是密码,那么应该进行多次加密,防止拖库后被破解。最大的反例就是csdn,600万用户名和密码由于数据库明文保存,被黑客攻击后遭到泄漏。

2 HMAC算法

HMAC算法将散列算法与一个密钥结合在一起,以阻止对签名完整性的破坏

2.1 语法

let hmac = crypto.createHmac(algorihtm,key);
hmac.update(data);
hmac.digest('hex');
复制代码
  • algorithm 是一个可用的摘要算法,例如 sha1、md5、sha256
  • key为一个字符串,用于指定一个PEM格式的密钥

2.2生成私钥

PEM是OpenSSL的标准格式,OpenSSL使用PEM文件格式存储证书和密钥,是基于Base64编码的证书.

windows版openSSL下载

openssl genrsa -out rsa_private.key 2048
复制代码

生成PEM格式的密钥

2.3加密示例

let crypro = require('crypto');
let fs = require('fs');
let key = fs.readFileSync(`${__dirname}/rsa_private.key`);
let hmac = crypto.createHmac('sha1',key);
hmac.update('牧濑红莉栖');
let result = hmac.digest('hex');
console.log(result) // a99a39b22a2272b070666194eede92ed1e9bbe46
复制代码

3 对称加密

与散列哈希算法不同的是,他是可逆的,加密解密,使用相同的密钥

blowfish、aes等算法是一种对称的加密算法,对称的意思就是加密和解密使用的是同一个密钥。

let crypto = require('crypto');
let fs = require('fs');
let key = fs.readFileSync(`${__dirname}/rsa_private.key`);
let cipher = crypto.createCipher('blowfish',key);
cipher.update('凤凰');
let result = cipher.final('hex');
console.log(result); // 

let deciper = crypto.createDecipher('blowfish',key);
//需要知道是用那种编码格式输出的
deciper.update(result,'hex');
let r = deciper.final('utf8');
console.log(r) // 凤凰
复制代码

4 非对称加密算法

  • 非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)
  • 公钥和私钥是一对,如果用公钥对数据加密,则只有对应的私钥才能解密,如果私钥加密,那么只有公钥才能解密
  • 因为加密和解密使用的是两个不同的密钥,所以这种算法叫做非对称加密算法

为私钥创建公钥

openssl rsa -in rsa_private.key -pubout -out rsa_public.key 
复制代码
let crypto = require('crypto');
let fs = require('fs');
let pubkey = fs.readFileSync(`${__dirname}/rsa_public.key`,'utf8');
let prikey = fs.readFileSync(`${__dirname}/rsa_private.key`,'utf8');

let result = crypto.publicEncrypt(pubkey,Buffer.from('凤凰院凶真'));
let r = crypto.privateDecrypt(prikey,result);

console.log(r.toString()); // '凤凰院凶真'
复制代码

5 签名

在网络中,私钥的拥有者可以在一段数据被发送前先对数据进行签名得到一个签名,通过网络吧此数据发送给接受者之后,数据的接收者可以通过公钥来对该签名进行验证,以确保这段数据是私钥的拥有者所发出的原始数据,且在网络中的传输过程中未被修改.

  • “Sign”类是生成签名的实用工具。它有两种使用方式:

    作为一个可写的stream,在这里,要签署的数据是写出来的,sign.sign()方法用于生成并返回签名

  • 使用sign.update()和sign.sign()方法生产签名。

  • crypto.createSign()方法用于创建Sign实例。Sign实例不能直接使用new关键字创建。

例:使用sign.write() sign.sign() 方法

let crypto = require('crypto');
let fs = require('fs')
let sign = crypto.createSign('SHA256');
sign.write('克里斯蒂娜');
sign.end();

let prikry = fs.readFileSync(`${__dirname}/rsa_private.key`);

console.log(sign.sign(prikry,'hex'));
复制代码

例:使用sign.update() sign.sign() 方法

let crypto = require('crypto');
let fs = require('fs')
let sign = crypto.createSign('SHA256');
sign.update('克里斯蒂娜');

let prikry = fs.readFileSync(`${__dirname}/rsa_private.key`);

console.log(sign.sign(prikry,'hex'));
复制代码

例:通过签名校验数据是否被修改

let fs = require('fs');
let crypto = require('crypto');
let path = require('path');
let private = fs.readFileSync(path.join(__dirname, 'rsa_private.key'));
let public = fs.readFileSync(path.join(__dirname, 'rsa_public.key'));
let str = '无限远点的牵牛星';
let sign = crypto.createSign('RSA-SHA256');

sign.update(str);
let signed = sign.sign(private,'hex');
console.log(signed);

let verify = crypto.createVerify('RSA-SH256');
verify.update(str);
let verifyResult = verify.verify(public,signed,'hex');
console.log(verifyResult) // true
复制代码

结语

crypto模块常用的加密算法的介绍到这里就结束了,如果你有更好的思路和想法,欢迎分享哦!

如果觉得还可以,请点赞鼓励一下,谢谢!

文章分类
前端