← Назад к вопросам

Для чего нужна Симметричная криптография?

1.0 Junior🔥 122 комментариев
#Soft Skills и рабочие процессы

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Симметричная криптография: назначение и применение

Симметричная криптография — это метод шифрования, где один и тот же ключ используется и для шифрования, и для расшифровки данных. Это критично для Frontend Security.

Основной принцип

Симметричная криптография = один ключ для всех операций

// Упрощенный пример (В реальности используйте TweetNaCl, libsodium, etc.)
const crypto = require('crypto');

// Один ключ
const sharedSecret = 'my-super-secret-key-32-chars!';

// Шифрование
function encrypt(plaintext) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(sharedSecret), iv);
  
  let encrypted = cipher.update(plaintext);
  encrypted = Buffer.concat([encrypted, cipher.final()]);
  
  return iv.toString('hex') + ':' + encrypted.toString('hex');
}

// Расшифровка (тот же ключ!)
function decrypt(encryptedText) {
  const parts = encryptedText.split(':');
  const iv = Buffer.from(parts[0], 'hex');
  const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(sharedSecret), iv);
  
  let decrypted = decipher.update(Buffer.from(parts[1], 'hex'));
  decrypted = Buffer.concat([decrypted, decipher.final()]);
  
  return decrypted.toString();
}

const message = 'Secret data';
const encrypted = encrypt(message);  // зашифровано
const decrypted = decrypt(encrypted); // расшифровано

Симметричная vs Асимметричная

ТипКлючейСкоростьИспользование
Симметричная1 (shared)БыстроШифрование данных
Асимметричная2 (публичный + приватный)МедленноОбмен ключами

Пример разницы:

// Симметричная (быстро, но нужно безопасно обменяться ключом)
const key = 'shared-secret';
const encrypted = encrypt(data, key);
const decrypted = decrypt(encrypted, key);

// Асимметричная (медленнее, но ключ обмена не нужен)
const { publicKey, privateKey } = generateKeyPair();
const encrypted = encryptPublic(data, publicKey);
const decrypted = decryptPrivate(encrypted, privateKey);

Назначение симметричной криптографии

1. Шифрование данных в transit (передача данных)

Кейс: HTTPS/TLS

// Браузер и сервер обмениваются асимметричными ключами
// Затем согласуют симметричный ключ для эффективного шифрования

// fetch с HTTPS — использует симметричное шифрование
const response = await fetch('https://api.example.com/data', {
  method: 'POST',
  body: JSON.stringify({ password: '***' })
  // Весь трафик зашифрован симметричным ключом!
});

Почему симметричная?

  • Быстрая передача больших данных
  • TLS согласует симметричный ключ сессии
  • Оптимально для высокой пропускной способности

2. Шифрование sensitive данных в локальном хранилище

Кейс: Сохранение токена или данных в localStorage

import nacl from 'tweetnacl';
import naclUtil from 'tweetnacl-util';

class SecureStorage {
  constructor(password) {
    // Дериватизируем пароль в ключ (KDF - Key Derivation Function)
    this.key = nacl.util.decodeBase64(password);
  }
  
  setItem(key, value) {
    // Генерируем nonce для каждого шифрования
    const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
    const encrypted = nacl.secretbox(
      naclUtil.decodeUTF8(JSON.stringify(value)),
      nonce,
      this.key
    );
    
    const stored = {
      nonce: naclUtil.encodeBase64(nonce),
      encrypted: naclUtil.encodeBase64(encrypted)
    };
    
    localStorage.setItem(key, JSON.stringify(stored));
  }
  
  getItem(key) {
    const stored = JSON.parse(localStorage.getItem(key));
    if (!stored) return null;
    
    const decrypted = nacl.secretbox.open(
      naclUtil.decodeBase64(stored.encrypted),
      naclUtil.decodeBase64(stored.nonce),
      this.key
    );
    
    return JSON.parse(naclUtil.encodeUTF8(decrypted));
  }
}

const storage = new SecureStorage(derivedPassword);
storage.setItem('authToken', 'secret-token-xyz');
const token = storage.getItem('authToken');

Почему симметричная?

  • Быстро шифровать/расшифровать при каждом доступе
  • Высокая производительность
  • Один браузер использует один ключ

3. End-to-end encryption (E2EE)

Кейс: Мессенджеры (Telegram, WhatsApp), конфиденциальные системы

// Упрощенный пример WhatsApp E2EE логики

class E2EEMessenger {
  constructor() {
    // Генерируем асимметричные ключи (один раз)
    this.keyPair = generateAsymmetricKeyPair();
    // Загружаем публичные ключи других пользователей
    this.publicKeys = new Map();
  }
  
  async sendMessage(recipientId, message) {
    // Генерируем случайный симметричный ключ для этого сообщения
    const messageKey = generateSymmetricKey();
    
    // Шифруем сообщение симметрично (быстро)
    const encryptedMessage = symmetricEncrypt(message, messageKey);
    
    // Шифруем ключ асимметрично отправителем (для получателя)
    const recipientPublicKey = this.publicKeys.get(recipientId);
    const encryptedKey = asymmetricEncrypt(messageKey, recipientPublicKey);
    
    // Отправляем оба
    await api.sendMessage({
      encryptedMessage,
      encryptedKey
    });
  }
  
  async receiveMessage(encryptedMessage, encryptedKey) {
    // Расшифровываем ключ асимметрично (только получатель может)
    const messageKey = asymmetricDecrypt(encryptedKey, this.keyPair.private);
    
    // Расшифровываем сообщение симметрично
    const message = symmetricDecrypt(encryptedMessage, messageKey);
    
    return message;
  }
}

Архитектура:

Отправитель                         Получатель
┌─────────────────┐                ┌──────────────────┐
│ Generate random │                │  Decrypt with    │
│ symmetric key   │                │  own private key │
│      (K)        │                │   to get (K)     │
└────────┬────────┘                └────────▲─────────┘
         │                                  │
         │                                  │
    [Encrypt msg]              [Decrypt msg with K]
    with key K (fast)                      ▲
         │                                  │
         └─► Encrypt K with receiver's ────┘
             public key (slow but once per msg)

Почему гибридный подход?

  • Симметричная шифрует большой контент (быстро)
  • Асимметричная обменивает ключи безопасно
  • Лучше производительности и безопасности

4. Аутентификация и целостность (HMAC)

Кейс: Проверка что данные не были изменены

const crypto = require('crypto');

// Используем симметричный ключ для создания подписи
function signData(data, secret) {
  return crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(data))
    .digest('hex');
}

function verifyData(data, signature, secret) {
  const expected = signData(data, secret);
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Использование
const secret = 'shared-secret';
const payload = { userId: 123, action: 'delete' };

const signature = signData(payload, secret);
// Отправляем payload + signature

// На сервере
if (verifyData(receivedPayload, receivedSignature, secret)) {
  console.log('Данные не были изменены');
} else {
  console.log('Данные были подделаны!');
}

Алгоритмы симметричной криптографии

Современные:

  • AES-256 (Advanced Encryption Standard) - стандарт
  • ChaCha20 - быстро на мобильных
  • XChaCha20 - с большим nonce

Устаревшие (НЕ использовать):

  • DES - уязвима (56-bit ключ)
  • 3DES - медленно

Безопасный обмен ключом

Проблема: Как обменяться симметричным ключом безопасно?

// Решение 1: Diffie-Hellman (DH)
// Оба генерируют случайный ключ, затем обмениваются публичными данными
// Результат: оба имеют одинаковый симметричный ключ

// Решение 2: Асимметричная криптография
// Асимметрично шифруем симметричный ключ

// Решение 3: Out-of-band обмен
// Заранее передали ключ другим способом (лично, SMS, etc.)

Frontend практика

Что я делаю на фронтенде:

// 1. Полагаюсь на HTTPS (TLS использует симметричное шифрование)
// 2. Шифрую sensitive данные перед сохранением в localStorage
// 3. Использую secure cookies (HttpOnly, Secure флаги)
// 4. Для E2EE мессенджеров - реализую гибридное шифрование

// Пример: Сохранение приватного ключа в браузере
function storePrivateKeySecurely(privateKey, password) {
  const encryptionKey = deriveKeyFromPassword(password); // KDF
  const encrypted = symmetricEncrypt(privateKey, encryptionKey);
  localStorage.setItem('privateKey', encrypted);
}

function retrievePrivateKey(password) {
  const encrypted = localStorage.getItem('privateKey');
  const encryptionKey = deriveKeyFromPassword(password);
  return symmetricDecrypt(encrypted, encryptionKey);
}

Безопасность ключа

Как защитить ключ:

  1. Никогда не хардкодить в клиентском коде
  2. Хранить в безопасном месте (Web Crypto API, IndexedDB с шифрованием)
  3. Использовать KDF (PBKDF2, Argon2) для дериватизации из пароля
  4. Регулярно ротировать ключи
  5. Использовать случайный nonce для каждого шифрования

Итого

Симметричная криптография нужна для:

  1. TLS/HTTPS — шифрование трафика между браузером и сервером
  2. Шифрование localstorage — защита от XSS атак
  3. E2EE мессенджеры — конфиденциальность сообщений
  4. HMAC — проверка целостности данных
  5. Быстрое шифрование больших данных — оптимальная производительность

Главные преимущества:

  • Быстро (в тысячи раз быстрее асимметричной)
  • Надежно (если правильно использовать)
  • Простоустановить (один ключ)

Главная проблема:

  • Обмен ключом (решается асимметричной криптографией или Diffie-Hellman)
Для чего нужна Симметричная криптография? | PrepBro