Криптография правильно: не изобретайте свою
В криптографии «работает на моих тестах» не значит «безопасно».
Don't roll your own crypto — правило не изобретать собственные шифры и протоколы, а использовать проверенные временем библиотеки и стандарты.
Почему своя криптография — почти всегда ошибка
Шифр может корректно шифровать и расшифровывать и при этом быть катастрофически нестойким: уязвимость прячется в математике и в тонкостях реализации, которые не видны по функциональным тестам. Проверенные алгоритмы (AES, ChaCha20, RSA, кривые) годами ломают лучшие криптографы — и не сломали. Самописный шифр такой проверки не проходил. То же касается «своих» режимов, паддингов и генераторов — почти все классические провалы именно там.
Здесь стоит развеять интуицию, которая часто подводит. Кажется: «я придумал хитрое преобразование, его же никто не знает — значит, не взломает». Это и есть запрещённый принцип «безопасность через неясность»: стойкость не должна зависеть от того, что алгоритм секретен. Стойкая криптография устроена наоборот — алгоритм публичен и многократно проанализирован, секретен только ключ. Если ваша схема держится лишь на том, что её код не опубликован, она рухнет, как только код станет известен (а он станет: декомпиляция, утечка, инсайдер).
Опасны и невинные на вид «улучшения» поверх стандартных примитивов: дважды зашифровать «для надёжности», склеить пароль с данными собственной формулой, обрезать или дополнить блок «как удобнее». Каждое такое решение незаметно вводит свойство, которого нет в проверенной схеме, и часто именно оно становится точкой взлома. Правило простое: вы не должны принимать криптографических решений, которые за вас уже приняли авторы стандарта.
Используйте высокоуровневые библиотеки
Чем меньше криптографических решений вы принимаете руками, тем лучше. Современные библиотеки дают «коробочные» функции с безопасными умолчаниями: одна функция «зашифровать», одна «расшифровать», правильный режим и IV под капотом. Это и есть главный практический совет урока: ищите самый высокоуровневый интерфейс, который решает вашу задачу целиком, и не спускайтесь к «кубикам» вроде голого блочного шифра, если только вы не криптограф, отвечающий именно за это. Чем выше уровень API, тем меньше у вас возможностей выбрать небезопасный режим, забыть про аутентификацию или переиспользовать nonce.
// Уязвимо: ручная сборка из низкоуровневых примитивов
cipher = AES.new(key, AES.MODE_ECB) // ECB раскрывает повторяющиеся блоки!
ct = cipher.encrypt(pad(plaintext)) // без аутентификации -> подмена незаметна
// Безопасно: высокоуровневый AEAD с безопасными умолчаниями
ct = secretbox.encrypt(plaintext, key) // случайный nonce + аутентификация внутри
pt = secretbox.decrypt(ct, key) // подмена шифртекста будет обнаружена
Аутентифицированное шифрование (AEAD)
Просто «зашифровать» мало: атакующий, не зная содержимого, может изменить шифртекст, и расшифровка молча выдаст искажённые данные. AEAD (AES-GCM, ChaCha20-Poly1305) шифрует и добавляет тег целостности: при любой подмене расшифровка завершится ошибкой. Это безопасный дефолт для шифрования данных.
Чтобы понять, почему одного шифрования недостаточно, вспомните, что шифрование скрывает смысл, но не запрещает менять биты. В некоторых режимах перевернуть конкретный бит шифртекста — значит предсказуемо перевернуть соответствующий бит расшифрованного текста. Атакующий, не зная ключа, может прицельно поправить, скажем, поле «сумма» или «роль» в зашифрованном сообщении. AEAD закрывает это тем, что вместе с шифртекстом считает криптографический тег по содержимому: изменили хоть один бит — тег не сойдётся, и библиотека вернёт ошибку вместо «починенных» данных.
У AEAD есть и приятный бонус — «связанные данные» (associated data): к шифртексту можно привязать незашифрованный, но аутентифицированный контекст, например идентификатор получателя или версию формата. Эти данные передаются открыто, но подменить их незаметно нельзя — они тоже входят в тег. Это удобно, когда часть метаданных должна оставаться читаемой, но не должна подделываться.
Что и чем защищать
| Задача | Правильный инструмент |
| пароли пользователей | argon2/bcrypt (хеш, не шифрование!) |
| данные «в покое» (диск, БД) | AEAD (AES-GCM) с ключом из KMS |
| данные «в пути» (сеть) | TLS |
| проверка целостности | HMAC / подпись |
Частая путаница — пытаться «зашифровать» пароли. Пароли не шифруют (это обратимо), а хешируют специальным алгоритмом — см. раздел про аутентификацию.
Как работает под капотом: nonce и управление ключами
Большинство режимов требуют уникальный nonce/IV на каждое шифрование одним ключом; повтор nonce в GCM раскрывает данные. Поэтому nonce генерируют криптостойким рандомом и никогда не переиспользуют. Не менее важно управление ключами: ключ хранят в KMS/хранилище, ротируют, не кладут рядом с шифртекстом и не зашивают в код. Самый стойкий шифр бесполезен, если ключ лежит в репозитории.
Стоит отдельно понять, почему повтор nonce так опасен. Поточные режимы превращают ключ и nonce в псевдослучайный поток, которым «маскируют» данные. Если для двух разных сообщений использован один и тот же ключ и nonce, поток маскировки одинаков — и математическая разница двух шифртекстов выдаёт разницу двух открытых текстов, постепенно раскрывая содержимое и даже подрывая аутентификацию. Именно поэтому nonce обязан быть уникальным: его не обязательно скрывать, но нельзя повторять. На практике его либо берут из CSPRNG достаточной длины, либо ведут как монотонный счётчик, гарантирующий неповторяемость.
Управление ключами — отдельная дисциплина с понятной целью: ограничить «радиус поражения» при компрометации. Помогают разделение ключей по назначению (один — для платежей, другой — для сессий), оболочечное шифрование (данные шифруются ключом данных, а сам ключ данных — мастер-ключом из KMS) и регулярная ротация. Тогда утечка одного ключа не раскрывает всё сразу, а замена ключа не требует перешифровать терабайты — достаточно перевыпустить обёрнутый ключ данных.
Частые ошибки
- Свой шифр или протокол. Берите стандарт и проверенную библиотеку.
- Режим ECB. Раскрывает структуру данных; используйте AEAD.
- Шифрование без аутентификации. Допускает незаметную подмену; нужен AEAD/HMAC.
- Повтор nonce/IV, ключ рядом с данными. Сводит стойкость на нет.
Итоги
- Не изобретайте криптографию: используйте проверенные библиотеки и стандарты.
- Шифруйте с аутентификацией (AEAD), чтобы ловить подмену.
- Пароли хешируют, данные шифруют, целостность проверяют HMAC/подписью.
- Уникальный nonce и грамотное управление ключами критичны.