共计 4017 个字符,预计需要花费 11 分钟才能阅读完成。
NodeJs 简明教程将从零开始学习 NodeJs 相关知识,助力 JS 开发者构建全栈开发技术栈!
本文是 NodeJs 简明教程的第六篇,将介绍 NodeJs crypto 模块相关的基本操作。
crypto 模块提供了加密功能,包括对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装。
Hash
Hash 类是用于创建数据哈希值的工具类。
哈希算法严格来说并不属于加密算法,传统意义上的 加密 是与 解密 相配对的。哈希算法能够保证被哈希的内容不被篡改。针对任意长度的输入数据都可以产生固定位数的哈希值。
crypto 模块对 hash 的操作是一致的,除了算法名不一致之外,本文以 md5 和 sha1 作为示例。
MD5
const crypto = require('crypto'); | |
const hash = crypto.createHash('md5'); // 创建 MD5 hash 示例 | |
hash.update('111111'); // 待计算 hash 的数据 | |
console.log(hash.digest('hex')); |
以上例程输出 96e79218965eb72c92a549dd5a330112
SHA1
const crypto = require('crypto'); | |
const hash = crypto.createHash('sha1'); // 创建 MD5 hash 示例 | |
hash.update('111111'); // 待计算 hash 的数据 | |
console.log(hash.digest('hex')); |
以上例程输出 3d4f2bf07dc1be38b20cd6e46949a1071f9d0e3d
Base64
Base64
并不是 crypto
模块的成员,但是跟本节内容比较相近,所以放过来了。Base64 是一套编码算法,常用在二进制数据编码上。
Base64 编码
const data = '111111'; | |
const encodedData = Buffer.from(data, 'utf8').toString('base64'); // 输入编码为 utf8, 输出为 base64 | |
console.log(encodedData); |
以上例程输出 MTExMTEx
Base64 解码
const data = 'MTExMTEx'; | |
const decodedData = Buffer.from(data, 'base64').toString('utf8'); // 输入编码为 base64, 输出编码为 utf8 | |
console.log(decodedData); |
以上例程输出111111
Hmac
Hmac 类是用于创建加密 Hmac 摘要的工具。
Hmac 算法也是一种 hash 算法,但是它需要一个密钥,针对同样的输入,传统的 hash 算法输出是固定的。
但是 Hmac 的输出会随着密钥的不同而不同。
const crypto = require('crypto'); | |
const hmac = crypto.createHmac('sha256', 'secret-key'); | |
hmac.update('Hello, world!'); | |
console.log(hmac.digest('hex')); |
以上例程输出 f4d850b1017eb4e20e0c58443919033c90cc9f4fe889b4d6b4572a4a0ec2d08a
AES
AES 是一种常用的对称加密算法,加解密都用同一个密钥。
AES 加密
const crypto = require('crypto'); | |
const cipher = crypto.createCipheriv('aes192', '111111111111111111111111', '1111111111111111') | |
var crypted = cipher.update('1', 'utf8', 'hex'); | |
crypted += cipher.final('hex'); | |
console.log(crypted); |
以上例程输出 5bb3e6eb39e502b5fa74d93796087efa
说明:
createCipheriv
原型如下:
crypto.createCipheriv(algorithm,key,iv [,options])
-
iv
是初始化向量,可以 为空 或者 16 字节的字符串 -
key
是加密密钥,根据选用的算法不同,密钥长度也不同,对应关系如下:-
aes128
对应16 位
长度密钥 -
aes192
对应24 位
长度秘钥 -
aes256
对应32 位
长度密钥
-
AES 解密
const crypto = require('crypto'); | |
const cipher = crypto.createDecipheriv('aes192', '111111111111111111111111', '1111111111111111') | |
var data = cipher.update('5bb3e6eb39e502b5fa74d93796087efa', 'hex', 'utf8'); // 输入数据编码为 hex(16 进制),输出为 utf8 | |
data += cipher.final('utf8'); | |
console.log(data); |
以上例程输出1
crypto.createDecipheriv
方法原型与 crypto.createCipher
一致,这里不在赘述。
RSA
RSA 算法是一种非对称加密算法,即由一个私钥和一个公钥构成的密钥对,通过私钥加密,公钥解密,或者通过公钥加密,私钥解密。其中,公钥可以公开,私钥必须保密。
生成密钥对
使用 RSA 算法前必须提供密钥对,本文使用 openssl
命令进行生成。
-
openssl genrsa -out private.pem 2048
生成2048 位
长度的私钥
-
openssl rsa -in private.pem -pubout -out public.pem
导出公钥
这样在当前目录我们就得到了 private.pem
和public.pem
RSA 加密
const crypto = require('crypto'); | |
const fs = require('fs'); | |
const privateKey = fs.readFileSync('./private.pem', { encoding: 'utf8'}); | |
const encodedData = crypto.privateEncrypt(privateKey, Buffer.from('111111','utf8')); // 传入 utf8 编码的数据 | |
console.log(encodedData.toString('hex')); |
以上例程输出
44a1b50b9639e4cbe17d55ca57dcb041387acadae3d3721fd9803a3a33091a36d59977feaa6caad990e58b9542c26297de6014e20819f0a71eadd0793bfe0fac834f30d2a05f8b329a3b2409e9f8b7fbd7de3734ada00228b84027568be58a2a34ccf0c4a8b2d02c58eef510931423ed5f40c696361b606df11609248b271aebcd17f9a113f98a8fa86c9c45bd609256f4779ce01ea3027171fffb35e695f1c38553aecafb72a2f46a9012246fde0f2934eacba8932bca38e228f4f4294873ed75d9acf79ab854897ebaab2375384b2da682c1b2e2b49b0592929067b3d5a11971d912629a178691345f7f88137343588b5c51d60643e5c00998484727b8c4a8
RSA 解密
const crypto = require('crypto'); | |
const fs = require('fs'); | |
const publicKey = fs.readFileSync('./public.pem', { encoding: 'utf8'}); | |
const encodedData = '44a1b50b9639e4cbe17d55ca57dcb041387acadae3d3721fd9803a3a33091a36d59977feaa6caad990e58b9542c26297de6014e20819f0a71eadd0793bfe0fac834f30d2a05f8b329a3b2409e9f8b7fbd7de3734ada00228b84027568be58a2a34ccf0c4a8b2d02c58eef510931423ed5f40c696361b606df11609248b271aebcd17f9a113f98a8fa86c9c45bd609256f4779ce01ea3027171fffb35e695f1c38553aecafb72a2f46a9012246fde0f2934eacba8932bca38e228f4f4294873ed75d9acf79ab854897ebaab2375384b2da682c1b2e2b49b0592929067b3d5a11971d912629a178691345f7f88137343588b5c51d60643e5c00998484727b8c4a8'; | |
const rawData = crypto.publicDecrypt(publicKey, Buffer.from(encodedData, 'hex')); // 传入 hex(16 进制)数据 | |
console.log(rawData.toString('utf8')); |
以上例程输出
111111
结语
常用的加解密、哈希、编解码用法已经介绍完毕,读后有疑问请加微信群讨论。
也可以关注公众号获取本系列持续更新: