import crypto from 'crypto' const ALGORITHM = 'aes-256-gcm' const KEY_LENGTH = 32 const IV_LENGTH = 16 const TAG_LENGTH = 16 const SALT_LENGTH = 32 const ITERATIONS = 100000 // 从密码派生密钥 function deriveKey(password: string, salt: Buffer): Buffer { return crypto.pbkdf2Sync(password, salt, ITERATIONS, KEY_LENGTH, 'sha256') } // 生成随机密钥(用于主密钥) export function generateMasterKey(): string { return crypto.randomBytes(KEY_LENGTH).toString('hex') } // 加密数据 export function encrypt(plaintext: string, password: string): string { const salt = crypto.randomBytes(SALT_LENGTH) const key = deriveKey(password, salt) const iv = crypto.randomBytes(IV_LENGTH) const cipher = crypto.createCipheriv(ALGORITHM, key, iv) const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]) const tag = cipher.getAuthTag() // 格式: salt:iv:tag:encrypted (全部 hex) return [ salt.toString('hex'), iv.toString('hex'), tag.toString('hex'), encrypted.toString('hex'), ].join(':') } // 解密数据 export function decrypt(ciphertext: string, password: string): string { try { const [saltHex, ivHex, tagHex, encryptedHex] = ciphertext.split(':') if (!saltHex || !ivHex || !tagHex || !encryptedHex) { throw new Error('Invalid ciphertext format') } const salt = Buffer.from(saltHex, 'hex') const iv = Buffer.from(ivHex, 'hex') const tag = Buffer.from(tagHex, 'hex') const encrypted = Buffer.from(encryptedHex, 'hex') const key = deriveKey(password, salt) const decipher = crypto.createDecipheriv(ALGORITHM, key, iv) decipher.setAuthTag(tag) const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]) return decrypted.toString('utf8') } catch (error) { throw new Error('Decryption failed: ' + (error as Error).message) } } // 简单加密(不带 salt,用于可逆加密) export function simpleEncrypt(plaintext: string, key: string): string { const iv = crypto.randomBytes(IV_LENGTH) const keyBuffer = Buffer.from(key, 'hex').slice(0, KEY_LENGTH) const cipher = crypto.createCipheriv(ALGORITHM, keyBuffer, iv) const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]) const tag = cipher.getAuthTag() return iv.toString('hex') + ':' + tag.toString('hex') + ':' + encrypted.toString('hex') } // 简单解密 export function simpleDecrypt(ciphertext: string, key: string): string { try { const [ivHex, tagHex, encryptedHex] = ciphertext.split(':') const iv = Buffer.from(ivHex, 'hex') const tag = Buffer.from(tagHex, 'hex') const encrypted = Buffer.from(encryptedHex, 'hex') const keyBuffer = Buffer.from(key, 'hex').slice(0, KEY_LENGTH) const decipher = crypto.createDecipheriv(ALGORITHM, keyBuffer, iv) decipher.setAuthTag(tag) const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]) return decrypted.toString('utf8') } catch (error) { throw new Error('Decryption failed: ' + (error as Error).message) } }