Методы шифрования данных: критический разбор для Web3

Пользователь нажимает «создать кошелёк», получает 12 или 24 слова, прячет их в заметки — и уверен, что данные «зашифрованы». Разработчик добавляет в приложение доказательства с нулевым разглашением — и в презентации появляется слово «анонимность».

Методы шифрования данных: критический разбор для Web3

Команда переводит казначейство на мультиподпись — и кто-то говорит, что средства теперь «защищены криптографией».

Формально в каждой из этих фраз есть криптография. Но шифрование — только в одной части этой картины, и именно путаница понятий создаёт самые дорогие ошибки в Web3-продуктах. Методы шифрования данных решают задачу конфиденциальности: превратить читаемую информацию в вид, бесполезный для постороннего, но восстанавливаемый владельцем ключа. Подписи подтверждают право действия, хеши связывают данные, zero-knowledge-доказательства проверяют утверждение без раскрытия секрета. Это не взаимозаменяемые детали.

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

Шифрование в Web3 начинается не с блокчейна

Есть неудобная, но полезная реальность: публичный блокчейн по умолчанию плохо подходит для хранения секретов. Всё, что приложение отправило в calldata, записало в события контракта или сохранило в публичное состояние, стоит считать видимым. Даже если поверх транзакции использован сложный протокол приватности, он не отменяет прозрачность окружающих данных.

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

Условно весь путь данных в Web3-приложении можно разделить на четыре слоя:

  • Данные на устройстве. Локальный кеш, вложения, приватные настройки, сессионные данные. Здесь нужен защищённый контейнер и понятная модель доступа: кто именно может расшифровать файл после разблокировки устройства или кошелька.
  • Передача между участниками. Сообщения, документы, ключи доступа, синхронизация между устройствами. Здесь важны не только секретность, но и защита от подмены.
  • Хранение вне цепочки. Сервер, облачное или децентрализованное файловое хранилище. Сам факт, что файл лежит не на централизованном сервере, ещё не делает его приватным.
  • Публичная цепочка. Здесь стоит размещать минимум необходимого: хеши, ссылки, доказательства, зашифрованные пакеты — но не открытые персональные или коммерческие данные.

Ожидание обычно такое: «мы используем блокчейн, значит данные надёжны». Реальность проще: блокчейн может надёжно фиксировать факт, порядок и состояние, но конфиденциальность нужно проектировать отдельно.

В Web3 защищённые данные — это не те, что лежат «в блокчейне», а те, для которых заранее определены ключ, получатель, срок доступа и способ восстановления.

Симметричные алгоритмы: почему одного AES недостаточно

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

Главный стандарт здесь — AES. Он работает с блоками по 128 бит и имеет варианты с ключами длиной 128, 192 и 256 бит. В продуктовых обсуждениях часто звучит упрощение: «берём AES-256 — значит, всё максимально безопасно». Но длина ключа — только часть решения. Если выбрать режим работы неправильно, сильный базовый алгоритм не спасёт интерфейс и данные от вполне прикладной атаки.

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

AES-GCM: рабочий выбор при грамотной реализации

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

Это важный UX-момент. Пользователь не обязан понимать разницу между «не смогли прочитать» и «данные пришли, но были подменены». Продукт обязан обработать оба случая безопасно. Нельзя показывать повреждённый текст как будто он настоящий, нельзя «на всякий случай» игнорировать ошибку проверки тега.

AES-GCM особенно уместен, когда команда использует зрелые системные криптобиблиотеки и не пишет криптографию вручную. Но у него есть строгая эксплуатационная дисциплина: параметры шифрования, включая уникальные значения nonce, должны генерироваться и храниться корректно. Красивый выбор алгоритма на архитектурной схеме ничего не значит, если два сообщения уходят с повторённым служебным значением при одном ключе.

OWASP рекомендует выбирать именно аутентифицированные режимы — прежде всего GCM или CCM. Режимы CBC и CTR сами по себе не подтверждают целостность. Их можно применять в более сложной конструкции с отдельной проверкой подлинности, но в обычном продукте это добавляет лишние точки отказа. ECB же для прикладных данных почти всегда плохая идея: он способен выдавать повторяющиеся визуальные и структурные паттерны в шифротексте.

ChaCha20-Poly1305: когда важна предсказуемая бесшовность

Второй практичный вариант — ChaCha20-Poly1305. Это тоже аутентифицированное шифрование, но устроенное иначе. В стандартизированной конструкции используется 256-битный ключ, 96-битный nonce и 128-битный тег Poly1305.

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

Вот как я бы сравнил эти варианты на уровне выбора продукта, а не маркетингового списка «топовых шифров».

ПараметрAES-GCMChaCha20-Poly1305
Тип защитыАутентифицированное шифрованиеАутентифицированное шифрование
Что получает продуктСекретность данных и проверку целостностиСекретность данных и проверку целостности
Ключевой риск внедренияОшибки в работе с nonce, тегами и библиотечными настройкамиПовтор nonce с тем же ключом; нарушение этого правила критично
Где выглядит естественноПродукты с опорой на зрелую системную инфраструктуруСетевые протоколы и кроссплатформенные сценарии
Что не решаетКому выдать ключ, где его хранить, что попадёт в публичную цепочкуТе же задачи управления ключами и метаданными

Здесь нет универсального победителя. В конкретной системе выбор зависит от окружения, библиотек, производительности, совместимости и уже существующей архитектуры ключей. Алгоритмы шифрования в блокчейне нельзя выбрать одним пунктом в техническом задании, потому что значительная часть работы происходит вообще не внутри цепочки.

Nonce: маленькое поле, на котором ломается большая безопасность

Nonce — это служебное значение, которое участвует в шифровании. Его не обязательно скрывать, но оно должно подчиняться правилам конкретного алгоритма. В ChaCha20-Poly1305 nonce длиной 96 бит обязан быть уникальным для каждого вызова шифрования с одним и тем же ключом.

Именно здесь у команд часто возникает опасная мысль: «96 бит — огромное пространство, давайте просто сгенерируем случайное значение». Но спецификация ChaCha20-Poly1305 прямо предупреждает против такого подхода и указывает на счётчик как на способ обеспечивать уникальность. Причина понятна: продукту нужна не абстрактно высокая вероятность удачи, а гарантия, что один и тот же nonce не повторится в пределах одного ключа.

Я бы закладывал это не в комментарий к функции, а в саму модель данных. Например, у каждого ключа для сессии или файла должен быть свой управляемый счётчик, а состояние этого счётчика нельзя бездумно откатывать при восстановлении бэкапа. Иначе система, которая «работала в тестах», может начать повторять nonce после переустановки приложения, сброса локальной базы или конкурирующей отправки сообщений с нескольких устройств.

Минимальная практическая дисциплина выглядит так:

1. Не придумывать формат криптопакета на глаз. Использовать библиотеку, которая возвращает шифротекст, nonce и тег в документированном формате, либо явно описать сериализацию и покрыть её тестами совместимости.

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

3. Разделять ключи по назначению. Ключ, которым зашифровали локальный кеш, не должен автоматически служить ключом для переписки, резервной копии и обмена файлами.

4. Отказываться от расшифровки при любой ошибке аутентификации. Не пытаться «вытащить хотя бы текст». В безопасном интерфейсе сообщение либо проверено, либо его нет.

5. Не писать собственный AES, Poly1305 или генератор nonce. Это не экономия зависимости, а лишняя поверхность для ошибки, которую трудно заметить на ревью.

В стандартах GCM тоже продолжается ужесточение подхода к тегам аутентификации. NIST обсуждает отказ от тегов короче 96 бит в проекте пересмотра рекомендаций. Это пока не финальная действующая норма, но направление очевидно: экономить на целостности ради нескольких байтов в новом протоколе — странная оптимизация.

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

Асимметричная часть: как передать ключ, не передавая секрет

Симметричное шифрование быстро работает с данными, но создаёт вопрос онбординга: как два участника получают общий секретный ключ, если они прежде не встречались в безопасном канале?

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

В реальном продукте этот гибридный подход обычно удобнее, чем попытка шифровать каждый мегабайт асимметричным алгоритмом. Пользователь добавляет контакт, приложение получает его публичный ключ, согласует секрет и дальше работает быстро. Снаружи это может выглядеть как один клик «отправить защищённый файл». Внутри — отдельная жизнь ключей, идентификаторов, ротации и восстановления.

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

ML-KEM и постквантовая миграция: не кнопка «квантобезопасно»

В августе 2024 года NIST опубликовал FIPS 203 — стандарт для ML-KEM, механизма инкапсуляции ключей. Его задача не в том, чтобы напрямую зашифровать пользовательский файл или сообщение. ML-KEM помогает двум сторонам получить общий секрет через публичный канал; потом этот секрет используют обычные симметричные средства для шифрования и аутентификации.

Стандарт определяет наборы ML-KEM-512, ML-KEM-768 и ML-KEM-1024. По мере роста параметров увеличивается ожидаемая стойкость и растут издержки по производительности и размеру данных. Это не повод называть любой продукт с упоминанием ML-KEM «готовым к постквантовой эпохе».

Ожидание: команда меняет один алгоритм в SDK и закрывает вопрос на десятилетия. Реальность: криптографическая миграция затрагивает формат ключей, протокол регистрации, хранение публичных ключей, совместимость клиентов, обновление бэкапов и сценарий, в котором старые устройства ещё не умеют работать по новой схеме.

Для Web3 это особенно чувствительно. Сеть, кошелёк, мессенджер на базе кошелька и смарт-контракт могут обновляться с разной скоростью. FIPS 203 стандартизирует ML-KEM как механизм согласования секрета, но сам по себе не говорит, что конкретная блокчейн-сеть уже внедрила его или определила сроки такой миграции.

Практичный план выглядит менее эффектно, но полезнее:

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

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

ZKP, мультиподпись и хеши: полезные вещи, но не методы шифрования данных

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

МеханизмЧто делаетЧего не делает
ШифрованиеСкрывает содержимое и позволяет восстановить его владельцу ключаНе доказывает само по себе право потратить средства
ХешированиеСоздаёт необратимый цифровой отпечаток данныхНе позволяет восстановить исходный текст и не является шифрованием
Доказательство с нулевым разглашениемПодтверждает истинность утверждения без раскрытия свидетеляНе превращает все связанные данные транзакции в секретные
Мультиподпись M-of-NТребует M подтверждений из N ключей для авторизации действияНе шифрует seed-фразу, баланс или данные транзакции

Доказательства с нулевым разглашением особенно легко переоценить. Они позволяют убедительно показать: «условие выполнено», не раскрывая сам секрет. Например, можно доказать принадлежность к группе или корректность вычисления. Но если приложение передало лишние данные в calldata, оставило информативное событие контракта или сохранило идентификатор пользователя в открытом хранилище, ZKP не сотрёт эти следы.

Даже идеально построенная схема не отменяет сетевые метаданные. Повторное использование одного RPC-провайдера, IP-адреса, браузерной сессии или привычного паттерна действий способно связать операции между собой. Приватность — это не один примитив, а цепочка решений, и самое слабое звено часто находится за пределами криптокода.

Мультиподпись, в свою очередь, отлично решает задачу совместного контроля. BIP-11 описывает модель M-of-N: для расходования средств нужны M подписей из N возможных ключей. Для казначейства DAO, семейного хранилища или команды это может быть разумным снижением риска единоличной ошибки. Но мультиподпись не делает активы «зашифрованными». Она меняет правила авторизации.

Seed-фраза BIP-39: это резервное представление секрета, а не шифрованный бэкап

Самый болезненный разрыв между ожиданием и реальностью я вижу именно здесь. Пользователь воспринимает seed-фразу как пароль от аккаунта. На деле фраза BIP-39 — это человекочитаемое представление исходной энтропии, из которого детерминированный кошелёк получает seed для дальнейшего создания ключей.

В BIP-39 исходная энтропия имеет размер от 128 до 256 бит. Слова берутся из словаря на 2048 позиций, а получение итогового 512-битного seed использует PBKDF2-HMAC-SHA512 с 2048 итерациями. Это тщательно определённый способ восстановления кошелька, а не зашифрованная копия одного приватного ключа.

Из этого следуют вполне земные правила:

  • seed-фразу нельзя отправлять в поддержку, вводить на неизвестном сайте или хранить в облачной заметке без отдельного надёжного шифрования;
  • фраза открывает не «одну монету», а потенциально всю иерархию ключей, зависящую от конкретного кошелька и путей деривации;
  • дополнительная парольная фраза может изменить результат, но не заменяет безопасное хранение исходной фразы;
  • скриншот seed в фотоплёнке — это не резервная стратегия, а удобная цель для синхронизации, бэкапов и вредоносных приложений.

Здесь хороший интерфейс должен быть чуть настойчивее обычного. Не просто показать 12 слов и кнопку «Я сохранил», а объяснить последствия, проверить восстановление в контролируемом сценарии и не создавать ложное чувство безопасности иконками замка.

Что я бы выбрал для нового Web3-продукта

Если задача — построить приложение с приватными данными, я бы не начинал с вопроса «AES или какой-нибудь модный протокол». Сначала стоит описать юзкейс: что именно скрываем, от кого, где данные будут жить, кому и как откроется доступ, что случится при потере устройства.

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

Стойкость протоколов передачи данных рождается не из самого длинного названия алгоритма. Она появляется, когда команда не повторяет nonce, не игнорирует ошибки проверки тега, не кладёт секреты в calldata и не заставляет пользователя быть криптографом, чтобы безопасно отправить сообщение.

Хорошая криптография в Web3 ощущается не как сложность. Она ощущается как отсутствие лишнего трения: данные открываются у того, кому положено, транзакция требует нужного числа подтверждений, а публичная инфраструктура не узнаёт больше, чем ей действительно необходимо.

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

Почему нельзя просто хранить зашифрованные данные в блокчейне?
Публичный блокчейн плохо подходит для хранения секретов, так как всё, что попадает в calldata или события контракта, является видимым. Шифрование должно применяться до публикации, чтобы в сеть уходил только защищенный шифротекст.
В чем разница между AES-GCM и ChaCha20-Poly1305?
Оба алгоритма являются методами аутентифицированного шифрования. AES-GCM чаще используется в системах со зрелой инфраструктурой, а ChaCha20-Poly1305 удобен для сетевых протоколов и кроссплатформенных сценариев.
Что будет, если повторно использовать nonce при шифровании?
Повторное использование nonce с одним и тем же ключом нарушает правила безопасности алгоритмов, что может привести к компрометации данных. Для обеспечения уникальности nonce рекомендуется использовать счетчики.
Является ли мультиподпись способом шифрования активов?
Нет, мультиподпись (M-of-N) лишь меняет правила авторизации действий, требуя подтверждения от нескольких ключей. Она не шифрует seed-фразу, баланс или данные транзакции.
Защищает ли использование ZKP все данные транзакции?
Нет, доказательства с нулевым разглашением лишь подтверждают истинность утверждения без раскрытия секрета. Они не делают все связанные данные транзакции секретными, если те были переданы в открытом виде.