Crypto-js для JavaScript (Node.js): полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Crypto-js для JavaScript (Node.js): полное руководство с примерами

В современной веб-разработке безопасность данных является критически важным аспектом. Будь то хранение паролей пользователей, передача конфиденциальной информации по сети или защита файлов от несанкционированного доступа — криптография лежит в основе этих процессов. Библиотека Crypto-js предоставляет мощный и удобный набор криптографических алгоритмов для экосистемы JavaScript, работая как в браузере, так и в среде Node.js.

Данная библиотека реализует широкий спектр стандартных криптографических функций: симметричное шифрование (AES, DES, TripleDES), хеширование (MD5, SHA-1, SHA-256, SHA-512), вычисление HMAC, а также генерацию случайных чисел и работу с кодировками (Base64, Hex, UTF-8). Crypto-js не зависит от нативных модулей операционной системы, что делает её идеальным выбором для изоморфных приложений (код, работающий и на клиенте, и на сервере).

В этой статье мы подробно разберём установку библиотеки, основные методы с примерами кода, а также рассмотрим реальный практический пример использования Crypto-js для защиты данных в веб-приложении. Материал будет полезен как начинающим разработчикам, так и опытным специалистам, желающим систематизировать свои знания о криптографии в JavaScript.

Установка

Для установки Crypto-js в проекте Node.js выполните следующую команду в терминале:

npm install crypto-js

После установки вы можете импортировать библиотеку в свой код:

// Для Node.js (CommonJS)
const CryptoJS = require("crypto-js");

// Для ES Modules (если используется "type": "module" в package.json)
import CryptoJS from "crypto-js";

Быстрый старт: минимальный рабочий пример

Давайте начнём с простейшего примера — шифрования и дешифрования строки с использованием алгоритма AES:

const CryptoJS = require("crypto-js");

// Исходное сообщение
const message = "Hello, Crypto-js!";

// Секретный ключ (должен быть надёжным в реальном приложении)
const secretKey = "my-secret-key-123";

// Шифрование
const ciphertext = CryptoJS.AES.encrypt(message, secretKey).toString();
console.log("Зашифрованное сообщение:", ciphertext);

// Дешифрование
const bytes = CryptoJS.AES.decrypt(ciphertext, secretKey);
const decryptedMessage = bytes.toString(CryptoJS.enc.Utf8);
console.log("Расшифрованное сообщение:", decryptedMessage);

Этот пример демонстрирует базовый цикл работы с симметричным шифрованием: мы преобразуем исходный текст в зашифрованную строку (Base64), а затем восстанавливаем исходное сообщение с помощью того же ключа.

Основные методы/функции/классы

Рассмотрим ключевые возможности Crypto-js. Для каждого метода приведена сигнатура, краткое описание и рабочий пример.

1. CryptoJS.AES.encrypt() / CryptoJS.AES.decrypt()

Сигнатура: CryptoJS.AES.encrypt(message, key, [options]) и CryptoJS.AES.decrypt(ciphertext, key, [options])

Что делает: Реализует симметричное шифрование и дешифрование по алгоритму AES (Advanced Encryption Standard). Поддерживает режимы ECB, CBC, CFB, OFB, CTR и размер ключа 128/192/256 бит.

const CryptoJS = require("crypto-js");

const message = "Секретные данные";
const key = "supersecretkey123";

// Шифрование с указанием режима и IV (вектор инициализации)
const iv = CryptoJS.lib.WordArray.random(16); // 16 байт для AES-128
const encrypted = CryptoJS.AES.encrypt(message, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
}).toString();

console.log("Зашифровано (CBC):", encrypted);

// Дешифрование
const decrypted = CryptoJS.AES.decrypt(encrypted, key, {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8);

console.log("Расшифровано:", decrypted);

2. CryptoJS.SHA256()

Сигнатура: CryptoJS.SHA256(message)

Что делает: Вычисляет SHA-256 хеш от переданного сообщения. Возвращает объект WordArray, который можно преобразовать в строку Hex или Base64.

const CryptoJS = require("crypto-js");

const data = "Hello, world!";
const hash = CryptoJS.SHA256(data);

console.log("SHA-256 (Hex):", hash.toString(CryptoJS.enc.Hex));
console.log("SHA-256 (Base64):", hash.toString(CryptoJS.enc.Base64));

3. CryptoJS.HmacSHA256()

Сигнатура: CryptoJS.HmacSHA256(message, key)

Что делает: Вычисляет HMAC (Hash-based Message Authentication Code) с использованием алгоритма SHA-256. Используется для проверки целостности и аутентичности сообщения.

const CryptoJS = require("crypto-js");

const message = "Важное сообщение";
const secret = "мой-секретный-ключ";

const hmac = CryptoJS.HmacSHA256(message, secret);
console.log("HMAC-SHA256:", hmac.toString(CryptoJS.enc.Hex));

4. CryptoJS.MD5()

Сигнатура: CryptoJS.MD5(message)

Что делает: Вычисляет MD5 хеш. Внимание: MD5 считается криптографически нестойким и не рекомендуется для использования в системах безопасности. Подходит только для контроля целостности некритичных данных.

const CryptoJS = require("crypto-js");

const text = "Проверка целостности";
const md5Hash = CryptoJS.MD5(text);
console.log("MD5:", md5Hash.toString());

5. CryptoJS.enc.Base64.stringify() / CryptoJS.enc.Base64.parse()

Сигнатура: CryptoJS.enc.Base64.stringify(wordArray) и CryptoJS.enc.Base64.parse(base64String)

Что делает: Преобразует WordArray в строку Base64 и обратно. Полезно для кодирования бинарных данных в текстовый формат.

const CryptoJS = require("crypto-js");

// Кодирование
const wordArray = CryptoJS.enc.Utf8.parse("Hello, Base64!");
const base64String = CryptoJS.enc.Base64.stringify(wordArray);
console.log("Base64:", base64String);

// Декодирование
const decodedWordArray = CryptoJS.enc.Base64.parse(base64String);
const decodedString = decodedWordArray.toString(CryptoJS.enc.Utf8);
console.log("Декодировано:", decodedString);

6. CryptoJS.lib.WordArray.random()

Сигнатура: CryptoJS.lib.WordArray.random(numberOfBytes)

Что делает: Генерирует криптографически стойкий набор случайных байт. Используется для создания векторов инициализации (IV), соли или ключей.

const CryptoJS = require("crypto-js");

// Генерация 32 случайных байт (256 бит)
const randomBytes = CryptoJS.lib.WordArray.random(32);
console.log("Случайные байты (Hex):", randomBytes.toString(CryptoJS.enc.Hex));
console.log("Случайные байты (Base64):", randomBytes.toString(CryptoJS.enc.Base64));

7. CryptoJS.PBKDF2()

Сигнатура: CryptoJS.PBKDF2(password, salt, [options])

Что делает: Реализует функцию формирования ключа на основе пароля (Password-Based Key Derivation Function 2). Позволяет получить криптостойкий ключ из пароля, используя соль и множество итераций.

const CryptoJS = require("crypto-js");

const password = "user_password_123";
const salt = CryptoJS.lib.WordArray.random(16);

const key = CryptoJS.PBKDF2(password, salt, {
    keySize: 256 / 32, // 256 бит
    iterations: 10000,
    hasher: CryptoJS.algo.SHA256
});

console.log("Сгенерированный ключ (Hex):", key.toString(CryptoJS.enc.Hex));
console.log("Соль (Hex):", salt.toString(CryptoJS.enc.Hex));

8. CryptoJS.TripleDES.encrypt() / CryptoJS.TripleDES.decrypt()

Сигнатура: CryptoJS.TripleDES.encrypt(message, key, [options]) и CryptoJS.TripleDES.decrypt(ciphertext, key, [options])

Что делает: Реализует шифрование/дешифрование по алгоритму Triple DES (3DES). Используется для совместимости с устаревшими системами.

const CryptoJS = require("crypto-js");

const message = "Legacy data";
const key = "24bytekeyfortripledes!!"; // Ключ должен быть 24 байта

const encrypted = CryptoJS.TripleDES.encrypt(message, key).toString();
console.log("3DES Encrypted:", encrypted);

const decrypted = CryptoJS.TripleDES.decrypt(encrypted, key).toString(CryptoJS.enc.Utf8);
console.log("3DES Decrypted:", decrypted);

Реальный практический пример

Рассмотрим полноценный пример создания безопасного менеджера паролей. Приложение будет шифровать пароли пользователя с использованием мастер-пароля, сохранять их в файл и дешифровать при необходимости.

const CryptoJS = require("crypto-js");
const fs = require("fs");
const readline = require("readline");

// Настройки шифрования
const ITERATIONS = 100000;
const KEY_SIZE = 256 / 32;
const SALT_SIZE = 32;

class PasswordManager {
    constructor(masterPassword) {
        this.masterPassword = masterPassword;
        this.salt = CryptoJS.lib.WordArray.random(SALT_SIZE);
        this.encryptionKey = this._deriveKey(masterPassword);
        this.vault = {};
    }

    // Вывод ключа из мастер-пароля
    _deriveKey(password) {
        return CryptoJS.PBKDF2(password, this.salt, {
            keySize: KEY_SIZE,
            iterations: ITERATIONS,
            hasher: CryptoJS.algo.SHA512
        });
    }

    // Шифрование отдельной записи
    _encryptEntry(plaintext) {
        const iv = CryptoJS.lib.WordArray.random(16);
        const encrypted = CryptoJS.AES.encrypt(plaintext, this.encryptionKey, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        return {
            iv: iv.toString(CryptoJS.enc.Hex),
            data: encrypted.toString()
        };
    }

    // Дешифрование записи
    _decryptEntry(entry) {
        const iv = CryptoJS.enc.Hex.parse(entry.iv);
        const decrypted = CryptoJS.AES.decrypt(entry.data, this.encryptionKey, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        return decrypted.toString(CryptoJS.enc.Utf8);
    }

    // Добавление пароля
    addPassword(service, username, password) {
        const plaintext = JSON.stringify({ username, password });
        this.vault[service] = this._encryptEntry(plaintext);
        console.log(`✅ Пароль для ${service} добавлен`);
    }

    // Получение пароля
    getPassword(service) {
        if (!this.vault[service]) {
            console.log(`❌ Сервис "${service}" не найден`);
            return null;
        }
        try {
            const decrypted = this._decryptEntry(this.vault[service]);
            const { username, password } = JSON.parse(decrypted);
            console.log(`🔑 ${service}: ${username} / ${password}`);
            return { username, password };
        } catch (error) {
            console.log("❌ Ошибка дешифрования. Возможно, неверный мастер-пароль.");
            return null;
        }
    }

    // Сохранение хранилища в файл
    saveToFile(filename) {
        const data = {
            salt: this.salt.toString(CryptoJS.enc.Hex),
            vault: this.vault
        };
        fs.writeFileSync(filename, JSON.stringify(data, null, 2));
        console.log(`💾 Хранилище сохранено в ${filename}`);
    }

    // Загрузка хранилища из файла
    loadFromFile(filename) {
        if (!fs.existsSync(filename)) {
            console.log("❌ Файл хранилища не найден");
            return false;
        }
        const raw = fs.readFileSync(filename, "utf8");
        const data = JSON.parse(raw);
        this.salt = CryptoJS.enc.Hex.parse(data.salt);
        this.encryptionKey = this._deriveKey(this.masterPassword);
        this.vault = data.vault;
        console.log(`📂 Хранилище загружено из ${filename}`);
        return true;
    }

    // Вывод списка сервисов
    listServices() {
        console.log("📋 Список сохранённых сервисов:");
        Object.keys(this.vault).forEach(service => {
            console.log(`  - ${service}`);
        });
    }
}

// Демонстрация работы
async function main() {
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    const question = (query) => new Promise(resolve => rl.question(query, resolve));

    console.log("🔐 Менеджер паролей (Crypto-js Demo)");
    console.log("=".repeat(40));

    const masterPassword = await question("Введите мастер-пароль: ");
    const manager = new PasswordManager(masterPassword);

    // Попробуем загрузить существующее хранилище
    const loaded = manager.loadFromFile("vault.json");

    while (true) {
        console.log("\nВыберите действие:");
        console.log("1. Добавить пароль");
        console.log("2. Получить пароль");
        console.log("3. Список сервисов");
        console.log("4. Сохранить и выйти");

        const choice = await question("Ваш выбор (1-4                    

Рекомендаций