Node.js 中的密码学:用于加密和哈希的 crypto 模块
在现代 Web 开发中,数据安全是一个至关重要的方面。Node.js 提供了内置的 crypto 模块,该模块实现了密码学功能,包括对称和非对称加密、哈希以及消息认证码(HMAC)的计算。在本文中,我们将通过实际示例详细讲解 crypto 模块的主要功能。
安装与引入
crypto 模块是 Node.js 标准库的一部分,因此无需额外安装。使用时只需导入它:
const crypto = require('crypto');数据哈希
哈希是将数据单向转换为固定长度字符串的过程。最流行的算法是 SHA-256。哈希用于验证数据完整性和存储密码(需结合盐值)。
const data = "秘密消息";const hash = crypto.createHash('sha256') .update(data) .digest('hex');
console.log(`SHA-256 哈希: ${hash}`);// 输出:64 个字符的字符串为了提高密码安全性,务必使用盐值(salt)和 PBKDF2 或 bcrypt 算法。PBKDF2 示例:
const password = "用户密码";const salt = crypto.randomBytes(16).toString('hex');
crypto.pbkdf2(password, salt, 100000, 64, 'sha512', (err, derivedKey) => { if (err) throw err; console.log(`密码哈希: ${derivedKey.toString('hex')}`); console.log(`盐值: ${salt}`);});对称加密(AES)
对称加密使用相同的密钥进行加密和解密。最常用的算法是 AES(高级加密标准)。我们来看一下使用 AES-256-CBC 进行加密和解密的过程。
const algorithm = 'aes-256-cbc';const key = crypto.randomBytes(32); // 256 位密钥const iv = crypto.randomBytes(16); // 初始化向量
// 加密function encrypt(text) { const cipher = crypto.createCipheriv(algorithm, key, iv); let encrypted = cipher.update(text, 'utf8', 'hex'); encrypted += cipher.final('hex'); return { iv: iv.toString('hex'), encryptedData: encrypted };}
// 解密function decrypt(encryptedData, ivHex) { const decipher = crypto.createDecipheriv(algorithm, key, Buffer.from(ivHex, 'hex')); let decrypted = decipher.update(encryptedData, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return decrypted;}
// 使用示例const message = "机密数据";const encrypted = encrypt(message);console.log(`加密后: ${encrypted.encryptedData}`);
const decrypted = decrypt(encrypted.encryptedData, encrypted.iv);console.log(`解密后: ${decrypted}`);重要提示:切勿对不同的消息使用相同的 IV。每次加密操作都应生成新的随机 IV。
非对称加密(RSA)
非对称加密使用一对密钥:公钥用于加密,私钥用于解密。RSA 是最流行的算法。
const { generateKeyPairSync, publicEncrypt, privateDecrypt } = crypto;
// 生成密钥const { publicKey, privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' }});
// 使用公钥加密const dataToEncrypt = "用于 RSA 的秘密消息";const encryptedData = publicEncrypt(publicKey, Buffer.from(dataToEncrypt));console.log(`RSA 加密后: ${encryptedData.toString('base64')}`);
// 使用私钥解密const decryptedData = privateDecrypt(privateKey, encryptedData);co