Шифрование данных — основы
Шифрование данных — преобразование данных в нечитаемый формат с помощью криптографического ключа. Различают шифрование at rest (хранение) и in transit (передача). Без ключа расшифровка вычислительно невозможна.
Зачем нужно
GDPR, PCI DSS, HIPAA требуют шифрование персональных и платёжных данных. При утечке зашифрованной БД злоумышленник получает бесполезный зашифрованный blob без ключей. TLS защищает данные при передаче от прослушивания (MITM).
Где используется
- In transit: HTTPS (TLS 1.2/1.3) для всего трафика
- At rest: шифрование PII в БД (номера паспортов, карт)
- Шифрование файлов в хранилищах (S3, GCS)
- End-to-end шифрование в мессенджерах
Основной контент
Типы шифрования
Симметричное — один ключ для шифрования и расшифровки (AES-256-GCM)
Быстро, используется для данных at rest
Асимметричное — публичный ключ шифрует, приватный расшифровывает (RSA, EC)
Медленнее, используется для обмена ключами (TLS handshake)
Гибридное — TLS: асимметричное для обмена ключом, симметричное для данных
AES-256-GCM для шифрования данных at rest (Node.js)
const crypto = require('crypto');
const ALGORITHM = 'aes-256-gcm';
const KEY_LENGTH = 32; // 256 бит
const IV_LENGTH = 16; // 128 бит
function encrypt(plaintext, key) {
const iv = crypto.randomBytes(IV_LENGTH);
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
const encrypted = Buffer.concat([
cipher.update(plaintext, 'utf8'),
cipher.final,
]);
const authTag = cipher.getAuthTag; // GCM authentication tag
// Храним: iv + authTag + encrypted
return Buffer.concat([iv, authTag, encrypted]).toString('base64');
}
function decrypt(encryptedBase64, key) {
const data = Buffer.from(encryptedBase64, 'base64');
const iv = data.slice(0, IV_LENGTH);
const authTag = data.slice(IV_LENGTH, IV_LENGTH + 16);
const encrypted = data.slice(IV_LENGTH + 16);
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
decipher.setAuthTag(authTag);
return Buffer.concat([
decipher.update(encrypted),
decipher.final,
]).toString('utf8');
}
// Ключ из переменной окружения (32 байта base64)
const key = Buffer.from(process.env.ENCRYPTION_KEY, 'base64');
// Шифрование поля в БД
const encryptedSSN = encrypt(user.ssn, key);
await db.query('UPDATE users SET ssn_encrypted = $1', [encryptedSSN]);
TLS: настройка HTTPS в Node.js
const https = require('https');
const fs = require('fs');
const server = https.createServer({
key: fs.readFileSync('/path/to/private.key'),
cert: fs.readFileSync('/path/to/certificate.crt'),
minVersion: 'TLSv1.2', // Минимум TLS 1.2
ciphers: [
'TLS_AES_256_GCM_SHA384',
'TLS_CHACHA20_POLY1305_SHA256',
'ECDHE-RSA-AES256-GCM-SHA384',
].join(':'),
}, app);
HSTS — принудительный HTTPS
# Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# После включения браузеры не будут делать HTTP-запросы к сайту
Частые ошибки
- Использование ECB режима AES — шифрует блоки независимо, паттерны видны
- Повторное использование IV (Initialization Vector) с одним ключом — катастрофа для GCM
- Хранение ключа шифрования рядом с зашифрованными данными в одной БД
- Самописная криптография — используйте только проверенные библиотеки (Node.js crypto, libsodium)
- TLS 1.0/1.1 включён — эти версии уязвимы (POODLE, BEAST)