Криптография в TypeScript: шифрование и хеши на практике

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

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

Начать курс

Криптография в TypeScript: шифрование и хеши — полное руководство

Современная веб-разработка немыслима без обеспечения безопасности данных. TypeScript, как надстройка над JavaScript, предоставляет мощные инструменты для реализации криптографических функций как на стороне клиента, так и на сервере (Node.js). В этой статье мы подробно разберем основные криптографические примитивы: симметричное и асимметричное шифрование, хеширование, а также рассмотрим работу с цифровыми подписями. Все примеры кода написаны на TypeScript и готовы к использованию в реальных проектах.

1. Основы криптографии в TypeScript

В экосистеме TypeScript существует два основных подхода к криптографии:

  • Web Crypto API — встроенный API браузеров и Node.js (начиная с версии 15), предоставляющий низкоуровневый доступ к криптографическим операциям.
  • Сторонние библиотеки — такие как crypto-js, node-forge, bcryptjs для специфических задач.

Для серверной разработки на Node.js рекомендуется использовать встроенный модуль crypto, который является частью платформы и не требует установки дополнительных зависимостей.

2. Хеширование данных

Хеширование — это одностороннее преобразование данных фиксированной длины. Оно используется для хранения паролей, проверки целостности файлов и создания контрольных сумм.

2.1. SHA-256 с использованием Web Crypto API

async function hashSHA256(data: string): Promise<string> {
  const encoder = new TextEncoder();
  const dataBuffer = encoder.encode(data);
  const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// Пример использования
const myHash = await hashSHA256('Привет, мир!');
console.log(myHash); // 64 hex символа

2.2. Хеширование паролей с bcrypt

Для безопасного хранения паролей используйте специализированные алгоритмы с солью, например bcrypt:

import bcrypt from 'bcryptjs';

async function hashPassword(password: string): Promise<string> {
  const salt = await bcrypt.genSalt(12); // 12 раундов — хороший баланс
  return await bcrypt.hash(password, salt);
}

async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return await bcrypt.compare(password, hash);
}

// Пример
const password = 'MySecurePass!';
const hashedPassword = await hashPassword(password);
const isValid = await verifyPassword('MySecurePass!', hashedPassword);
console.log(isValid); // true

3. Симметричное шифрование

Симметричное шифрование использует один ключ для шифрования и дешифрования данных. Наиболее современный и безопасный алгоритм — AES-GCM, который обеспечивает как конфиденциальность, так и аутентификацию.

3.1. AES-GCM шифрование и дешифрование

interface EncryptedData {
  iv: Uint8Array;
  ciphertext: Uint8Array;
  tag: Uint8Array;
}

async function encryptAESGCM(
  plaintext: string,
  key: CryptoKey
): Promise<EncryptedData> {
  const encoder = new TextEncoder();
  const data = encoder.encode(plaintext);
  const iv = crypto.getRandomValues(new Uint8Array(12)); // 96-битный IV
  
  const encrypted = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    key,
    data
  );
  
  // GCM добавляет 16 байт аутентификационного тега в конец
  const ciphertext = new Uint8Array(encrypted.slice(0, encrypted.byteLength - 16));
  const tag = new Uint8Array(encrypted.slice(encrypted.byteLength - 16));
  
  return { iv, ciphertext, tag };
}

async function decryptAESGCM(
  encrypted: EncryptedData,
  key: CryptoKey
): Promise<string> {
  // Объединяем ciphertext и tag для Web Crypto API
  const combined = new Uint8Array([...encrypted.ciphertext, ...encrypted.tag]);
  
  const decrypted = await crypto.subtle.decrypt(
    { name: 'AES-GCM', iv: encrypted.iv },
    key,
    combined
  );
  
  const decoder = new TextDecoder();
  return decoder.decode(decrypted);
}

// Генерация ключа
async function generateAESKey(): Promise<CryptoKey> {
  return await crypto.subtle.generateKey(
    { name: 'AES-GCM', length: 256 },
    true,
    ['encrypt', 'decrypt']
  );
}

4. Асимметричное шифрование и цифровые подписи

Асимметричная криптография использует пару клю

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