node.js_crypto 模块
crypto 模块提供了加密功能,实现了包括对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装。
Hash 算法
Hash 类是用于创建数据哈希值的工具类。
查看 crypto 模块支持的 hash 函数:crypto.getHashes()
const crypto = require('crypto');
// 创建哈希函数 sha256
const hash = crypto.createHash('sha256');
// 输入流编码:utf8、ascii、binary(默认)
hash.update('some data to hash', 'utf8');
// 输出编码:hex、binary、base64
console.log(hash.digest('hex'));
// 输出
// 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50
PBKDF2
PBKDF2 是 Node.js 的 crypto 模块原生支持的标准方法。
const salt = crypto.randomBytes(32);
const result = crypto.pbkdf2Sync(password, salt, 4096, 512, 'sha256');
Hmac 算法
Hmac 类是用于创建加密 Hmac 摘要的工具。
示例一:
const crypto = require('crypto');
const secret = 'abcdefg';
const hash = crypto.createHmac('sha256', secret)
.update('I love cupcakes')
.digest('hex');
console.log(hash);
加盐(salt)
盐值就是随机数值,用于在计算密码的哈希值时加强数据的安全性,可以有效抵御诸如字典攻击、彩虹表攻击等密码攻击媒介。
常见的 Hash 算法使用示例:
const crypto = require('crypto');
const md5 = crypto.createHash('md5');
let password = '123456';
let salt = 'hhug6dcKyCNBQ5sUC0i6hja5dCTqdSzV'; // 盐值
// 将密码拼接上任意长度的随机字符串后,再进行 Hash
md5.update(password+salt);
console.log(md5.digest('hex'));
// 输出
// b2d23b0443c319e574f1ea3f8bddc6e0
crypto.randomBytes() 方法可以生成随机数,用于作为密钥或者盐值:
const crypto = require('crypto');
// 1. 异步方法
crypto.randomBytes(32, (err, salt) => {
if (err) throw err;
// 记录盐值可读的字符串版本
console.log('salt: ' + salt.toString('hex'));
// 后续步骤:使用盐值
});
// 2. 同步方法
const buf = crypto.randomBytes(256);
加密(Cipher)和解密(Decipher)算法
对称加密算法
查看 Openssl 对称加密算法列表:
'use strict';
const crypto = require('crypto');
// 初始化参数
const text = 'Encryption Testing AES GCM mode'; // 要加密和解密的数据
const key = crypto.randomBytes(32); // 256 位的共享密钥
const iv = crypto.randomBytes(16); // 初始向量,16 字节
const algorithm = 'aes-256-gcm'; // 加密算法和操作模式
// 加密
const cipher = crypto.createCipheriv(algorithm, key, iv); // 初始化加密算法
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const tag = cipher.getAuthTag(); // 生成标签,用于验证密文的来源
// 解密
const decipher = crypto.createDecipheriv(algorithm, key, iv); // 初始化解密算法
decipher.setAuthTag(tag); // 传入验证标签,验证密文的来源
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted); // Encryption Testing AES GCM mode
AES-256-GCM 示例2:
- Github - crypto-aes-256-gem-demo.js
- GitHub: AES 简介
const { generateKeyPair } = require('crypto');
generateKeyPair('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki', // pkcs1、spki
format: 'pem'
},
privateKeyEncoding: {
type: 'pkcs8', // pkcs1、pkcs8、sec1
format: 'pem',
cipher: 'aes-256-cbc', // 对私钥使用 aes-256-cbc 算法加密后返回
passphrase: 'top secret' // aes-256-cbc 算法密钥
}
}, (err, publicKey, privateKey) => {
// Handle errors and use the generated key pair.
});
使用 RSA 2048 进行公钥加密,私钥解密
使用 OpenSSL 生成 2048位 RSA 密钥:
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const root = __dirname;
const publicKey = fs.readFileSync(path.join(root, './mypubkey.pem')).toString('ascii');
const privateKey = fs.readFileSync(path.join(root, './ mykey.pem')).toString('ascii');
const data = 'data to crypt';
// 公钥加密
const encryptData = crypto.publicEncrypt(publicKey, Buffer.from(data)).toString('base64');
console.log('encode', encryptData);
// 私钥解密
const decryptData = crypto.privateDecrypt(privateKey, Buffer.from(encryptData.toString('base64'), 'base64'));
console.log('decode', decryptData.toString());
签名(Sign)和验证(Verify)算法
签名算法示例:
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const root = __dirname;
// 加载公钥文件
const publicKey = fs.readFileSync(path.join(root, './rsa_public_key.pem')).toString('ascii');
const verify = crypto.createVerify('RSA-SHA256'); // 创建验证算法
verify.update('data to sign');
console.log(verify.verify(publicKey, result, 'hex'));
// 打印
// true
DH 密钥交换算法
DiffieHellman 类是一个用来创建 Diffie-Hellman 键交换的工具。 DiffieHellman 类的实例可以使用 crypto.createDiffieHellman() 方法。
const crypto = require('crypto');
const assert = require('assert');
// Generate Alice's keys...
const alice = crypto.createECDH('secp521r1');
const aliceKey = alice.generateKeys();
// Generate Bob's keys...
const bob = crypto.createECDH('secp521r1');
const bobKey = bob.generateKeys();
// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
// OK
参考
- Node.js 的加密模块 crypto 之使用 Hash 类计算数据的哈希值
- Node.js 的加密模块 crypto 之使用 Hmac 类计算哈希密钥
- Node.js 的加密模块 crypto 之使用 Cipher 类加密数据
- Node.js 的加密模块 crypto 之使用 Decipher 类解密数据
- Node.js 的加密模块 crypto 之使用 Sign 类生成数字签名并使用 Verify 类验证数字签名
- Node.js 的加密模块 crypto 之使用 DiffieHellman 类生成交换密钥
- Node.js 的加密模块 crypto 之使用 ECDH 类生成 EC Diffie-Hellman 交换密钥
- Identity and Data Security for Web DevelopmentReport abuse
- Node.js 使用 RSA 加密 / 解密
相关第三方库
- bcrypt——密码哈希函数
- bcrypt.js
- node-rsa
- node-forge