Разработчик вскрыл E2EE изнутри. Signal больше не кажется простым
25 июня, 2026

Разработчик вскрыл E2EE изнутри. Signal больше не кажется простым

Разработчик вскрыл E2EE изнутри. Signal больше не кажется простым

Два месяца спустя: как pet-проект на мессенджере превратился в урок архитектурного мышления

Два месяца назад независимый разработчик опубликовал статью о своём open-source проекте - E2EE-мессенджере Chaos. Никто не ожидал, что материал наделает столько шума. Сейчас, спустя шестьдесят дней активной доработки, проект вырос в полноценную распределённую систему - и заодно наглядно показал, почему Signal создавали годами.

От простого чата к архитектурному ограничению

Задача поначалу казалась понятной. Есть спецификации X3DH и Double Ratchet, есть WebCrypto, есть документация. Собери аккуратно - и готово. Примерно в этот момент, как сам признаёт автор, где-то вдалеке начинает смеяться инженер из Signal.

Главный вывод, к которому пришёл разработчик: E2EE - это не отдельная функция encrypt() и не изолированный криптосервис. Это архитектурное ограничение, которое прорастает через всю систему. Если сервер не должен видеть plaintext, это немедленно затрагивает базу данных, WebSocket, авторизацию, восстановление сессий, preview сообщений и даже то, что отображается в списке чатов. Хочешь решить задачу на серверной стороне - сначала спроси себя: а должен ли сервер вообще знать ответ? Чаще всего - нет.

Double Ratchet: на бумаге красиво, в жизни больнее

Ключевое техническое обновление за эти два месяца - реализация полноценного DH Ratchet. В первой версии проекта была начальная установка сессии через X3DH и симметрическая цепочка ключей, но без DH-составляющей Double Ratchet не работает break-in recovery. Именно на это указали в комментариях - и автор прислушался.

Суть механизма проста на словах. Каждое сообщение использует новый message key, старые ключи постепенно обесцениваются. Когда собеседник отвечает новым DH-ключом, обе стороны пересчитывают root key и получают свежие цепочки. Если атакующий каким-то образом добрался до текущего chain key - после следующего DH-обмена это знание перестаёт ему помогать. Не панацея, но критически важное свойство протокола. Кстати, чем-то это напоминает принцип ротации в игровых системах безопасности - как, например, war prime в Warframe меняет механику доступа к контенту, вынуждая игрока каждый раз проходить новый путь.

На практике же сразу вылезает целый букет неудобных вопросов:

  • что делать с out-of-order сообщениями
  • сколько skipped message keys безопасно хранить
  • как вести себя, если устройство долго было офлайн
  • как не сломать multi-device при DH-обмене
  • где заканчивается удобство и начинается снижение безопасности

Сервер должен быть «тупее» - и это комплимент

Один из самых показательных эпизодов проекта - история с preview последнего сообщения. В базе поле content выглядит как заглушка. Первая реакция: что-то сломалось. Потом приходит понимание: нет, именно так оно и должно работать.

В обычном мессенджере preview - это простой SQL-запрос. В E2EE-системе сервер хранит только зашифрованный конверт, а клиент сохраняет расшифрованный текст локально после получения. Архитектура становится неудобнее. Зато честнее.

Сегодня проект включает React-фронтенд, Electron-приложение, Spring Boot backend, STOMP/WebSocket, PostgreSQL, Redis, Docker Compose, Prometheus, Grafana, Loki, Caddy и Kubernetes-манифесты. Chaos - не конкурент Signal и не готовый продукт. Это живая лаборатория, в которой любое решение про ключи немедленно отзывается во всей остальной системе. И именно это не даёт проекту надоесть.