/** * Утилиты для шифрования/дешифрования данных * Использует AES-256-GCM для шифрования паролей */ const crypto = require('crypto'); // Ключ шифрования из переменной окружения const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY || crypto.randomBytes(32).toString('hex'); const ALGORITHM = 'aes-256-gcm'; /** * Получить ключ шифрования (32 байта) */ function getEncryptionKey() { // Если ENCRYPTION_KEY - hex строка, конвертируем в Buffer if (ENCRYPTION_KEY.length === 64) { return Buffer.from(ENCRYPTION_KEY, 'hex'); } // Иначе используем как есть и дополняем/обрезаем до 32 байт const key = Buffer.from(ENCRYPTION_KEY, 'utf8'); if (key.length === 32) return key; // Дополняем или обрезаем до 32 байт const result = Buffer.alloc(32); key.copy(result, 0, 0, Math.min(key.length, 32)); return result; } /** * Зашифровать текст * @param {string} text - Текст для шифрования * @returns {string} - Зашифрованная строка в формате iv:authTag:encryptedData (все в base64) */ function encrypt(text) { if (!text) return ''; const key = getEncryptionKey(); const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv(ALGORITHM, key, iv); let encrypted = cipher.update(String(text), 'utf8', 'base64'); encrypted += cipher.final('base64'); const authTag = cipher.getAuthTag(); // Формат: iv:authTag:encryptedData (все в base64) return `${iv.toString('base64')}:${authTag.toString('base64')}:${encrypted}`; } /** * Расшифровать текст * @param {string} encryptedText - Зашифрованная строка в формате iv:authTag:encryptedData * @returns {string} - Расшифрованный текст */ function decrypt(encryptedText) { if (!encryptedText) return ''; try { const parts = encryptedText.split(':'); if (parts.length !== 3) { throw new Error('Invalid encrypted format'); } const [ivBase64, authTagBase64, encryptedBase64] = parts; const iv = Buffer.from(ivBase64, 'base64'); const authTag = Buffer.from(authTagBase64, 'base64'); const encrypted = encryptedBase64; const key = getEncryptionKey(); const decipher = crypto.createDecipheriv(ALGORITHM, key, iv); decipher.setAuthTag(authTag); let decrypted = decipher.update(encrypted, 'base64', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } catch (error) { console.error('Decryption error:', error); throw new Error('Failed to decrypt data'); } } module.exports = { encrypt, decrypt, };