Crypto 小记
Node 中的Crypto 模块提供了加解密算法,包括hash,HAMC,加解密、签名以及验证等,每种算法都有自己的应用场景。下面详解介绍
散列算法(hash)
又称散列函数、哈希****函数,是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值(hash values,hash codes,hash sums,或hashes)的指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表。
Hash 的特点
-
hash值不可逆,无法根据hash 值推测出原本的数值
-
不同输入会有不同的输出
-
果两个散列值相同,两个输入值很可能是相同的,但也可能不同,这种情况称为“杂凑碰撞(collision),好的 hash 算法冲突概率会很低。
Hash 的应用:密码存储,页面版本、数据校验等。
常用的hash 算法:
获取所有 hash 算法
const crypto = require('crypto');
console.log(crypto.getHashes())
[
'RSA-MD4',
'RSA-MD5',
'RSA-MDC2',
'RSA-RIPEMD160',
'RSA-SHA1',
'RSA-SHA1-2',
'RSA-SHA224',
'RSA-SHA256',
'RSA-SHA3-224',
'RSA-SHA3-256',
'RSA-SHA3-384',
'RSA-SHA3-512',
'RSA-SHA384',
'RSA-SHA512',
'RSA-SHA512/224',
'RSA-SHA512/256',
'RSA-SM3',
]
常用的hash 算有:md5 、sha256 等。
使用hash 实例
const crypto = require('crypto');
const hash = crypto.createHash('sha256'); // 创建基于 sha256 算法的hash 对象
hash.update('111111', 'utf-8');//增加要添加摘要的数据,摘要输出前可以使用多次update
let value = hash.digest('hex');//输出摘要内容,输出后则不能再添加摘要内容
console.log(value) //bcb15f821479b4d5772bd0ca866c00ad5f926e3580720659cc80d39c9d09802a
- 多次update
var fs = require('fs');
const crypto = require('crypto');
const hash = crypto.createHash('sha256'); // 创建基于 sha256 算法的hash 对象
const rs = fs.createReadStream('./readme.txt');
rs.on('data', function (data) {
hash.update(data);
});
rs.on('end', function () {
let result = hash.digest('hex');
console.log(result); })
HMAC 算法
Hmac 算法可以看做是hash 算法的一种扩展,虽然hash算法是不可逆的,不能有hash 值反解出来原始值,但是可以通过"彩虹表",使用碰撞法,根据hash 值得到原始值。hmac 是将hash 算法和秘钥结合在一起,在计算hash值的时候增加秘钥。来防止对hash 值的破解。
用法
crypto.createHmac(algorithm, key[, options])
-
// algorithm : hash 算法 和hash 算法保持一致
-
// key: 加密秘钥,客户是string buffer 等类型
-
// 可选参数 options encoding <string> The string encoding to use when key is a string.
实例
const hash = crypto.createHmac('sha256', 'sdakljdjajkdlsajeiw');
hash.update('111111', 'utf-8');//增加要添加摘要的数据,摘要输出前可以使用多次update
let value = hash.digest('hex');//输出摘要内容,输出后则不能再添加摘要内容
console.log(value) //4eb53842bf5fee692014ba84ddab4b444aed7183bc334e1870ef33d8a2be43e8
对称加密
对称加密就是加解密需要使用相同的秘钥。
查看node中 提供了 Cipher 和 Decipher ,类来进行对称的加解密。node中提供的对称加解密的算法有:
console.log(crypto.getCiphers())
'aes-128-cbc',
'aes-128-cbc-hmac-sha1',
'aes-128-cbc-hmac-sha256',
'aes-128-ccm',
'aes-128-cfb',
.....
常用的 算法有: AES、blowfish 等
用法
加密
crypto.createCipheriv(algorithm, key, iv[, options])
-
algorithm**: 加密算法**
-
Key & iv : 秘钥和初始化向量
解密
crypto.createDecipheriv(algorithm, key, iv[, options])
-
algorithm**: 加密算法**
-
Key & iv : 秘钥和初始化向量
实例
// 加密
let secret = 'iamasecret111111';
let iv = crypto.randomBytes(16);
// let iv = Buffer.alloc(16, 0);
let content = 'password';
const cipher = crypto.createCipheriv("aes128", secret, iv);
cipher.update(content, "utf8");
let digest = cipher.final("hex");
console.log('加密后结果', digest);
// 解密
const decipher = crypto.createDecipheriv("aes128", secret, iv);
decipher.update(digest, "hex");
console.log(decipher.final("utf8"));
运行过程出现:
** Error: Invalid IV length
** Error: Invalid key length
在使用不同的算时,对秘钥和IV的长度是有要求不一样的。一般是 256 bits = 32 bytes 大小的密钥。同样地,aes128也是有要求的,需要 128bits =16 bytes
非对称加密
非对称加密即加密和解密用的秘钥是不一样的。就是公钥(publickey)和私钥(privatekey),公钥和私钥成对出现。公钥可以公开到网络上,私钥的安全性决定加解密的安全性。数据如果用公钥加密,只有用对应的私钥才能解密,如果用私钥加密,可以使用对应的公钥解密。
生成秘钥
# 生成私钥
openssl genrsa -out privatekey.pem 1024
# 生成公钥
openssl rsa -in privatekey.pem -pubout -out publickey.pem
用法
// 私钥加密
crypto.privateEncrypt(privateKey, buffer)
// 私钥解密
crypto.privateDecrypt(privateKey, buffer)
// 公钥加密
crypto.publicEncrypt(key, buffer)
// 公钥解密
crypto.publicDecrypt(key, buffer)
实例
// 公钥加密私钥解密
let publicKey = fs.readFileSync('./publickey.pem');
let privateKey = fs.readFileSync('./privatekey.pem');
let content = '我是内容';
let encData = crypto.publicEncrypt(publicKey, Buffer.from(content));
console.log('公钥加密结果', encData.toString('base64'));
let decData = crypto.privateDecrypt(privateKey, encData);
console.log('私钥解密结果', decData.toString());
//输出
// 公钥加密结果 Fjuvn1WMplihuNbhVywbzIFYpEhVcSu8wTgsqW2y8OZAlyNgQ5QlpoexhiCoUTrsQ+wLpFrhyN7I5IDPujT9XppupE/ysVpdKLJceDS3OEckgqPLbaIcwaxsCs7Uob1ufelxrotw+nz1OA+QU0tJKKx6lVdpsi+nS3svq2WA1W8=
// 私钥解密结果 我是内容
// 私钥加密,公钥解密
let publicKey = fs.readFileSync('./publickey.pem');
let privateKey = fs.readFileSync('./privatekey.pem');
let content = '我是内容';
let encData = crypto.privateEncrypt(privateKey, Buffer.from(content));
console.log('私钥加密结果:', encData.toString('base64'));
let decData = crypto.publicDecrypt(publicKey, encData);
console.log('公钥解密结果:', decData.toString());
// 输出
// 私钥加密结果: BJSY163/PhlCAyLWo8ky04flTr69aoi4fVhS16pAFXKnPONLOTkpyrm7DANXe74lMm7huNVzKnU8Go3T4Y7XKOHPh8FQrAo/3eZcvFK3TXsrCPRtDo/+WgQbZyve1k+AnJ1KWV8VPZSKPnmfXD+9FgZ2QTi+ILw+xQL+rEfMWAs=
// 公钥解密结果: 我是内容
签名&& 验签
签名和验签主要用于确保数据在传输过程中未被修改和伪造。在数据发送之前,数据方先用hash+私钥 得到一个数据签名值,并把数据和签名值同时传输给客户。客户拿到数据后,使用数据方的公钥对签名进行验签,来保证数据未被修改和伪造。
用法
let publicKey = fs.readFileSync('./publickey.pem');
let privateKey = fs.readFileSync('./privatekey.pem');
let content = '我是内容';
const sign = crypto.createSign('SHA256');
sign.update(content);
sign.end();
const signature = sign.sign(privateKey);
const verify = crypto.createVerify('SHA256');
verify.update(content);
verify.end();
console.log(verify.verify(publicKey, signature));
常见安全加密算法
- Advanced Encryption Standard (AES):这是一种对称密钥加密算法,被广泛应用于保护数据的机密性。它是目前最常用的加密算法之一,也是美国政府采用的标准加密算法之一。
- RSA:这是一种非对称密钥加密算法,用于加密和数字签名。RSA算法基于一个数学问题,即如何对两个大质数的乘积进行因式分解。RSA算法在许多应用程序中广泛使用,包括安全电子邮件、虚拟专用网络 (VPN)、数字证书等。
- Elliptic Curve Cryptography (ECC):这是一种非对称密钥加密算法,使用椭圆曲线上的点来代表密钥。ECC算法比传统的RSA算法更短,更快,更安全,因此在许多应用程序中被广泛使用,例如物联网、移动设备和无线传感器网络等。
- Blowfish:这是一种对称密钥加密算法,被广泛应用于保护数据的机密性。Blowfish算法是一种快速、高效、安全的加密算法,被广泛应用于各种应用程序中,例如虚拟专用网络 (VPN)、电子邮件加密等。
参考:
转载自:https://juejin.cn/post/7205546336082231356