Программное шифрование данных: какой алгоритм под какую задачу

Большинство инцидентов с «зашифрованными данными» начинается не со взлома AES и не с криптоанализа эллиптических кривых. Они начинаются с архитектурной ошибки уровня encrypt(data, password)

Программное шифрование данных: какой алгоритм под какую задачу

Во всех этих случаях алгоритм может быть формально корректным. Система — нет.

Программное шифрование данных не сводится к выбору между AES-256 и «чем-нибудь посовременнее». Нужно определить, что именно защищается: bulk data, сетевой трафик, ключи, парольный vault, подпись транзакции, долгоживущий архив. Затем — посмотреть на CPU, модель угроз, жизненный цикл ключей и протокол обмена. Маркетинговая формула «военное 256-битное шифрование» здесь бесполезна: она не сообщает ни режима работы, ни схемы аутентификации, ни того, как система обращается с nonce.

Нормальная криптоархитектура почти всегда гибридная. Асимметричная криптография доставляет или согласует ключ. Симметричная — шифрует полезную нагрузку. AEAD-режим гарантирует не только конфиденциальность, но и целостность. KDF делает пароль хоть сколько-нибудь пригодным материалом для ключа. Всё остальное — детали реализации. А детали в криптографии обычно и являются уязвимостью.

Симметричное и асимметричное шифрование: разные уровни стека

Первое разделение элементарно, но его продолжают игнорировать даже в продакшен-коде: симметричное и асимметричное программное шифрование решают разные задачи.

Симметричный алгоритм использует один секретный ключ для шифрования и расшифрования. Его зона ответственности — данные в объёме от одного сообщения до базы, диска или непрерывного VPN-трафика. AES и ChaCha20 относятся именно сюда.

Асимметричная схема работает с парой ключей: публичным и приватным. Она нужна, когда стороны ещё не обладают общим секретом, но хотят его получить по недоверенному каналу, либо когда требуется подпись. RSA, ECDH, ECDSA и современные постквантовые KEM не являются заменой AES-GCM для файлового хранилища. Это разные слои.

ПараметрСимметричное шифрованиеАсимметричное шифрование
Основная задачаЗащита больших объёмов данныхОбмен ключами, аутентификация, подписи
Типичные алгоритмыAES-GCM, ChaCha20-Poly1305RSA, ECDH, ML-KEM, ML-DSA
ПроизводительностьВысокая, подходит для потока и storageНа порядки ниже, для payload непригодна
Управление ключамиСтороны уже должны иметь общий секретПозволяет установить секрет через открытую сеть
Типичный объект обработкиФайл, БД, пакет, backup, дискСессионный ключ, challenge, подпись, сертификат
Основной риск реализацииПовтор nonce, неверный режим, утечка ключаНеверная валидация, downgrade, слабые параметры, утечка private key

RSA здесь особенно часто становится жертвой плохого дизайна. Минимально приемлемые сегодня ключи RSA — 2048 бит. Для долгосрочных сценариев встречаются 3072 и 4096 бит. Но увеличение ключа не превращает RSA в механизм шифрования архива или таблицы базы данных. Накладные расходы огромны, размер входного блока ограничен, производительность плохая. Если сервис «шифрует RSA пользовательские документы», его архитектура уже нуждается в ревью.

Рабочая конструкция выглядит иначе:

1. Генерируется случайный симметричный сессионный ключ.

2. Данные шифруются этим ключом через AEAD: AES-GCM или ChaCha20-Poly1305.

3. Сессионный ключ инкапсулируется или согласуется асимметричной схемой: ECDH, RSA в легаси-контуре, ML-KEM в постквантовом гибриде.

4. Метаданные шифротекста хранят версию алгоритма, nonce, ciphertext и authentication tag — но не секретный ключ, разумеется.

5. При ротации ключей перешифровывается ключ данных, а не обязательно весь массив данных. Иначе операция ротации превращается в дорогостоящий self-DoS.

Шифровать данные RSA — не «усиливать защиту». Это обычно означает, что автор схемы не разделил транспорт ключа и защиту payload.

Для смарт-контрактов и Web3-инфраструктуры это различие особенно практично. Подпись кошелька подтверждает владение ключом. Она не шифрует calldata. ECDH может вывести общий секрет для off-chain канала. Но приватность транзакции в публичной сети потребует уже иной конструкции: commitments, encryption, zk-SNARKs, иногда threshold decryption. Подменять один примитив другим — стандартный путь к красивой диаграмме в pitch deck и бесполезной системе в проде.

AES-GCM или ChaCha20-Poly1305: бенчмарк начинается с процессора

Когда задача сводится к шифрованию данных, выбор обычно остаётся между AES-GCM и ChaCha20-Poly1305. Оба варианта пригодны. Оба являются AEAD-схемами: они одновременно скрывают содержимое и аутентифицируют его. Если атакующий изменит ciphertext, корректная реализация должна отвергнуть расшифрование, а не вернуть «почти правильный» plaintext.

AES — блочный шифр со стандартным блоком 128 бит. Он допускает ключи 128, 192 и 256 бит; число раундов составляет 10, 12 и 14 соответственно. Для прикладной архитектуры важнее не эта таблица из учебника, а наличие аппаратного ускорения.

На современных x86-серверах AES-NI и аналогичные инструкции AMD дают AES существенное преимущество. На ARM ту же роль играют Cryptography Extensions. В зависимости от платформы аппаратное ускорение может дать прирост порядка 10–30 раз относительно чистой программной реализации. На такой машине ChaCha20 не получает бонусов за «легковесность»: AES-GCM обычно оказывается быстрее и экономнее по CPU.

На слабых ARM, отдельных мобильных SoC, IoT-устройствах и виртуализированных средах без доступа к криптографическим инструкциям расклад меняется. ChaCha20 хорошо работает в software-only исполнении, его потоковая конструкция эффективно ложится на обычные операции сложения, XOR и циклических сдвигов. В таких условиях ChaCha20-Poly1305 часто рациональнее AES-GCM.

Но слово «часто» здесь критично. Нельзя объявить ChaCha20 быстрее AES вообще. Это ложное сравнение без указания железа, библиотеки и размера буфера. Мы прогоняем такие тесты на целевой платформе, а не на ноутбуке разработчика и не по рекламной таблице криптобиблиотеки.

Практическая матрица выбора

СценарийБазовый выборПочему
Шифрование БД, резервных копий, файлов на сервере с AES-NIAES-256-GCM или AES-128-GCM по политике ключейАппаратное ускорение, широкая поддержка, высокая пропускная способность
TLS 1.3 на современных серверахAES-GCM при наличии AES-NI; ChaCha20-Poly1305 как альтернативаВыбор должен учитывать CPU клиента и сервера
Мобильное приложение или IoT без crypto extensionsChaCha20-Poly1305Предсказуемая software-производительность
Шифрование одиночных записей в приложенииAES-GCM либо ChaCha20-Poly1305Важнее корректная генерация nonce и управление ключами
Долгоживущий зашифрованный архивAEAD для данных + отдельная envelope-схема для ключейНужны ротация, versioning и миграция алгоритмов
Передача секрета новому получателюECDH/ML-KEM + симметричный AEADАсимметричная часть защищает ключ, не сам массив данных

AES-128 при корректном применении не является «слабым AES». У него 128-битный ключ и 10 раундов; практической атаки полного перебора такого ключа нет. AES-256 выбирают там, где политика требует запаса по длине ключа или система проектируется с учётом модели Гровера. Но AES-256 не компенсирует nonce, повторённый дважды. Уязвимость реализации обнуляет разницу между 128 и 256 битами с почти комичной эффективностью.

Для GCM рекомендуемый размер nonce — 96 бит. Это не декоративное соглашение. Большинство реализаций оптимизированы именно под эту длину, а безопасная работа требует уникальности nonce для каждого шифрования под одним ключом. Не «случайности с надеждой». Уникальности, которую можно доказать архитектурой.

Random nonce — не всегда достаточная инженерия

Если сервис генерирует nonce через CSPRNG, вероятность коллизии зависит от количества операций. Для ограниченных объёмов она может быть приемлемой. Для высоконагруженного multitenant storage, очереди событий или долговечного журнала стоит предпочесть управляемую схему:

  • отдельный data-encryption key на логический объект или ограниченный сегмент данных;
  • монотонный счётчик nonce, привязанный к ключу;
  • атомарное резервирование диапазонов при параллельной записи;
  • ротация ключа до исчерпания допустимого пространства nonce;
  • хранение version и key identifier вместе с ciphertext.

Здесь часто всплывает неприятный лог: два разных объекта имеют одинаковый key_id, одинаковый nonce и разный ciphertext. После этого расследование уже не про «возможную криптографическую слабость». Это компрометация.

ECB, nonce reuse и отсутствие аутентификации: три способа сломать хороший примитив

Режим ECB остаётся самым дешёвым индикатором того, что программные средства шифрования данных выбирались без понимания предмета. ECB шифрует одинаковые блоки одинаково. Данные не обязательно становятся открытым текстом, но их структура сохраняется: повторяющиеся фрагменты, поля, изображения, шаблоны. Классический «пингвин ECB» не мем и не исторический курьёз. Это наглядная демонстрация детерминизма там, где он не должен появляться.

ECB не годится для общего шифрования данных. Не «нежелателен». Не «устарел, но иногда допустим». Не годится.

Вторая ошибка опаснее: nonce reuse в AES-GCM или ChaCha20-Poly1305. Оба режима строятся так, что повтор nonce с тем же ключом разрушает модель безопасности. В потоковой части повторяется keystream. Если есть два ciphertext, полученных одним keystream, их XOR убирает этот поток и даёт XOR исходных plaintext. При известных фрагментах сообщения это быстро превращается в восстановление содержимого.

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

Третья ошибка — использовать encryption без authentication. Например, AES-CBC с padding, но без MAC; CTR без отдельной проверки целостности; «просто AES» из API. В таких схемах атакующий может менять биты ciphertext предсказуемым образом. В худших случаях появляются padding oracle и полноценная утечка plaintext через различия в обработке ошибок.

Нормальный выбор по умолчанию: AEAD.

  • AES-GCM — если есть аппаратное ускорение AES и nonce lifecycle контролируется.
  • ChaCha20-Poly1305 — если software-производительность приоритетна или железо не имеет AES acceleration.
  • XChaCha20-Poly1305 — когда архитектура выигрывает от расширенного nonce и библиотека предоставляет проверенную реализацию. Но расширенный nonce не освобождает от дисциплины ключей и версионирования формата.

Не стоит писать собственную обвязку вокруг блочного шифра, вручную собирать MAC и придумывать формат записи. Криптографические библиотеки уже предлагают высокоуровневые AEAD API. Если команда обходит их ради «гибкости», обычно она получает дополнительную поверхность атаки и ноль преимуществ.

В криптографии нет режима «почти правильно». Повтор nonce — не предупреждение в логе, а событие уровня инцидента.

Пароль не ключ: KDF против GPU-перебора

Пароль пользователя почти никогда не должен подаваться напрямую в AES, ChaCha20 или любой другой cipher API. Пароль — низкоэнтропийная строка, часто повторно используемая, иногда состоящая из восьми символов. Ключ — равномерный секрет фиксированной длины. Между ними необходим KDF.

Для парольных vault, зашифрованных экспортов и локальных хранилищ разумный выбор — Argon2. Его задача не в том, чтобы сделать пароль математически сильнее. Он повышает цену каждой попытки перебора, в том числе на GPU, за счёт memory-hard дизайна.

PBKDF2 остаётся распространённым вариантом для совместимости, но его параметры нельзя оставлять на уровне старых дефолтов. Практический нижний ориентир из текущих рекомендаций — 200 000–300 000 итераций. Значения порядка 5 000, а тем более 1 итерации — не конфигурация защиты, а приглашение к офлайн-перебору. Инциденты с хранилищами, где такие параметры реально применялись, уже показали, что «хэшированный пароль» без адекватного work factor ничего не гарантирует после утечки базы.

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

Рабочий формат зашифрованного vault-записа должен содержать:

  • идентификатор KDF и её параметры: память, число проходов, параллелизм либо число итераций;
  • уникальную salt;
  • версию схемы;
  • AEAD nonce;
  • ciphertext и tag;
  • идентификатор ключа или контекста, если используется envelope encryption.

Параметры не зашиваются намертво в бинарник. Они сериализуются рядом с данными. Иначе через три года миграция с PBKDF2 на Argon2 потребует угадывать, какой билд и какие дефолты были у конкретной записи. В аудите подобные форматы выглядят как археологический слой из констант.

Отделяйте ключи данных от ключей ключей

Для backend-системы пароль пользователя не должен быть единственным ключом, которым напрямую шифруются терабайты объектов. Рациональнее разделить роли:

1. Случайный DEK шифрует конкретный объект или небольшой сегмент данных.

2. KEK защищает DEK.

3. Пароль через Argon2 или PBKDF2 выводит ключ, который участвует в защите KEK либо открывает защищённый контейнер.

4. KMS или HSM хранит root material вне прикладной базы.

Это добавляет метаданные и усложняет код. Зато ротация ключей не требует переписывать каждый байт данных, а отзыв доступа к конкретному ключу становится технически выполнимой операцией, а не обещанием в security policy.

Гибридные схемы: ECDH сегодня, ML-KEM в контуре миграции

В TLS 1.3, VPN и большинстве корректных защищённых протоколов полезная нагрузка шифруется симметрично. При установлении сессии стороны договариваются о сессионном секрете через асимметрический механизм — например, ECDH. Далее этот секрет проходит через KDF, из него выводятся раздельные ключи на направления трафика, а пакеты шифруются AES-GCM или ChaCha20-Poly1305.

Это называется гибридной схемой. Она не компромисс и не временная заплатка. Это нормальная архитектура, потому что она использует сильную сторону каждого класса примитивов.

В августе 2024 года NIST стандартизировал ML-KEM, основанный на CRYSTALS-Kyber, для инкапсуляции ключей, а также ML-DSA для цифровых подписей. В инженерной реальности это не означает, что следует завтра вырезать ECDH и заменить его ML-KEM во всех протоколах. Такая миграция требует оценки библиотек, форматов, размеров сообщений, поддержки на стороне клиентов и риска downgrade.

Рациональный путь — hybrid key establishment: секрет выводится из классического компонента и постквантового компонента. Компрометация одного не должна автоматически ломать всю сессию при условии корректного комбинирования. Такая конструкция полезна против модели «harvest now, decrypt later»: трафик собирают сейчас в расчёте расшифровать его позже, когда появится достаточный квантовый ресурс.

Но постквантовый ярлык не отменяет базовой гигиены. Можно интегрировать ML-KEM и по-прежнему хранить private key в .env, повторять nonce в GCM и принимать неподписанные обновления ключей. Уязвимость на прикладном уровне выигрывает у любой стойкости решёток.

Где постквантовая миграция действительно оправдана

Не каждый сервис обязан срочно менять криптоконтур. Приоритет получают системы, где данные должны оставаться конфиденциальными много лет:

  • медицинские и финансовые архивы;
  • секреты инфраструктуры с долгим сроком жизни;
  • межорганизационные документы;
  • ключевой материал, используемый для долгоживущих root-of-trust;
  • закрытая телеметрия и исследовательские данные, ценность которых не исчезает через месяц.

Для короткоживущей сессии с данными, не имеющими долгой ценности, риск-профиль другой. Там сначала нужно убедиться, что TLS не отключает проверку сертификатов, сервис не логирует токены доступа, а ключи не размазаны по CI. Переход на постквантовый KEM при этих дефектах будет примером дорогой имитации безопасности.

Что выбирать на практике

Если требуется один прикладной ответ без криптографического фольклора, он выглядит так.

Для серверного шифрования файлов, записей БД и backup на современном железе берите AES-GCM через проверенную библиотеку и аппаратное ускорение. Настройте уникальные 96-битные nonce, разделите ключи по объектам или сегментам, заложите ротацию и версионирование формата.

Для мобильного клиента, браузерного кода и IoT без AES acceleration рассматривайте ChaCha20-Poly1305. Он не «более безопасный AES» и не универсальный победитель. Это хороший AEAD, который часто даёт лучший бенчмарк на software-only окружении.

Для паролей используйте Argon2. Если совместимость вынуждает оставить PBKDF2, поднимайте число итераций хотя бы в диапазон 200 000–300 000 и измеряйте задержку на реальном устройстве. Не на CI runner с другим CPU.

Для обмена симметричными ключами используйте ECDH или современную KEM-схему. RSA оставляйте для легаси и совместимости, а не выбирайте его для новых систем только потому, что название знакомо менеджеру.

Для долгоживущих секретов проектируйте криптоконтур с гибридным ML-KEM заранее. Не обязательно включать его везде немедленно, но формат зашифрованных данных и протокол согласования ключа должны пережить миграцию без тотального re-encrypt и остановки сервиса.

Финальный вердикт жёсткий: программное шифрование данных выбирают не по длине ключа на лендинге и не по списку модных алгоритмов. AES-GCM или ChaCha20-Poly1305 для payload, KDF для пароля, асимметричный механизм для доставки ключа, AEAD без самодельных режимов, nonce без коллизий, ключи вне исходников. Если хотя бы один из этих пунктов отсутствует, обсуждать «AES-256 против квантовых атак» преждевременно. Сначала нужно починить архитектуру.

Частые вопросы

Почему нельзя использовать RSA для шифрования больших файлов или баз данных?
RSA обладает низкой производительностью, имеет ограничения на размер входного блока и создает огромные накладные расходы, что делает его непригодным для защиты полезной нагрузки.
Что делать, если в системе нет аппаратного ускорения AES?
В условиях отсутствия AES-NI или аналогичных инструкций на ARM, рациональнее использовать ChaCha20-Poly1305, так как он эффективнее работает в программной реализации.
Почему повторное использование nonce в AES-GCM считается критической ошибкой?
Повтор nonce с одним и тем же ключом разрушает модель безопасности, позволяя атакующему восстановить исходные данные или скомпрометировать механизм аутентификации.
Сколько итераций PBKDF2 достаточно для защиты пароля?
Практический нижний ориентир для PBKDF2 составляет 200 000–300 000 итераций, чтобы усложнить офлайн-перебор пароля.
Нужно ли срочно переходить на постквантовые алгоритмы вроде ML-KEM?
Срочная миграция оправдана для систем с долгоживущими данными, которые должны оставаться конфиденциальными много лет, чтобы защититься от стратегии «собирай сейчас, расшифровывай потом».