// cryptoUtils.js const crypto = require('crypto'); // 默认的加密配置 const ALGORITHM = 'aes-256-gcm'; const IV_LENGTH = 12; // GCM 推荐的 IV 长度 const AUTH_TAG_LENGTH = 16; // GCM 认证标签长度 const SALT_LENGTH = 16; // 盐值长度 /** * 从共享密钥派生加密密钥 * @param {string} secret - 共享密钥 * @param {Buffer} salt - 盐值 * @returns {Buffer} 派生的密钥 */ function deriveKey(secret, salt) { // 使用 PBKDF2 算法从共享密钥派生加密密钥 return crypto.pbkdf2Sync(secret, salt, 10000, 32, 'sha256'); } /** * 加密数据 * @param {Buffer|string} data - 要加密的数据 * @param {string} secret - 共享密钥 * @returns {Object} 包含加密数据和相关参数的对象 */ function encrypt(data, secret) { // 生成随机盐值和初始化向量 const salt = crypto.randomBytes(SALT_LENGTH); const iv = crypto.randomBytes(IV_LENGTH); // 派生密钥 const key = deriveKey(secret, salt); // 创建加密器 const cipher = crypto.createCipheriv(ALGORITHM, key, iv); // 加密数据 let encrypted = cipher.update(data); encrypted = Buffer.concat([encrypted, cipher.final()]); // 获取认证标签 const authTag = cipher.getAuthTag(); // 返回加密结果和相关参数 return { data: encrypted, salt: salt, iv: iv, authTag: authTag }; } /** * 解密数据 * @param {Buffer} encryptedData - 加密的数据 * @param {Buffer} salt - 盐值 * @param {Buffer} iv - 初始化向量 * @param {Buffer} authTag - 认证标签 * @param {string} secret - 共享密钥 * @returns {Buffer} 解密后的数据 */ function decrypt(encryptedData, salt, iv, authTag, secret) { // 派生密钥 const key = deriveKey(secret, salt); // 创建解密器 const decipher = crypto.createDecipheriv(ALGORITHM, key, iv); // 设置认证标签 decipher.setAuthTag(authTag); // 解密数据 let decrypted = decipher.update(encryptedData); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted; } /** * 验证数据完整性 * @param {Buffer} data - 原始数据 * @param {Buffer} salt - 盐值 * @param {Buffer} iv - 初始化向量 * @param {Buffer} authTag - 认证标签 * @param {string} secret - 共享密钥 * @returns {boolean} 数据是否完整且未被篡改 */ function verifyIntegrity(data, salt, iv, authTag, secret) { try { // 尝试解密数据,如果认证标签不匹配会抛出异常 decrypt(data, salt, iv, authTag, secret); return true; } catch (error) { return false; } } module.exports = { encrypt, decrypt, verifyIntegrity, ALGORITHM, IV_LENGTH, AUTH_TAG_LENGTH, SALT_LENGTH };