Криптография в Node.js: модуль crypto для шифрования и хеширования
В современной веб-разработке безопасность данных — критически важный аспект. 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 = "user_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 (Advanced Encryption Standard). Рассмотрим шифрование и дешифрование с использованием 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)
Асимметричное шифрование использует пару ключей: открытый (public) для шифрования и закрытый (private) для расшифровки. 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);
console.log(`Расшифровано RSA: ${decryptedData.toString('utf8')}`);
Цифровые подписи и HMAC
HMAC (Hash-based Message Authentication Code) позволяет проверить подлинность и целостность сообщения с использованием секретного ключа.
const secret = 'my-secret-key';
const messageHmac = 'Важное сообщение';
const hmac = crypto.createHmac('sha256', secret)
.update(messageHmac)
.digest('hex');
console.log(`HMAC: ${hmac}`);
// Проверка подлинности
function verifyHmac(message, receivedHmac) {
const expectedHmac = crypto.createHmac('sha256', secret)
.update(message)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expectedHmac, 'hex'),
Buffer