← На главную

Безопасность, Сквозное Шифрование и Архитектура Системы

Обновлено: Июнь 2026 • Документация Чепухаграм

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

🔑

X25519 (ECDH)

Согласование общего ключа на базе эллиптических кривых (Curve25519) без передачи секрета по сети.

⚙️

AES-256-GCM

Симметричное шифрование блоков данных с проверкой целостности и подлинности (AEAD).

🔒

PBKDF2-HMAC-SHA256

Криптографическая деривация ключей из мастер-пароля с использованием 600,000 итераций.

📡

WebSockets & Drift DB

Реалтайм-доставка сообщений и локальное структурированное хранение истории в зашифрованном виде.

1. Сквозное шифрование (End-to-End Encryption)

С сквозным шифрованием (E2EE) ваши сообщения кодируются непосредственно перед отправкой на вашем устройстве и могут быть декодированы только на устройстве получателя. Серверная часть мессенджера Чепухаграм полностью изолирована от ключевой информации. Сервер функционирует исключительно как маршрутизатор зашифрованных бинарных пакетов и не способен восстановить исходный текст.

Схема согласования ключей (X25519 / ECDH)

Для создания защищенного канала используется протокол Диффи-Хеллмана на эллиптических кривых. Ниже представлена схема независимого вычисления общего секрета:

Вы
Ваш приватный ключ A (dA)
Ваш публичный ключ A (QA = dA * G)
Общий секрет (K = dA * QB)
публичный ключ A →
← публичный ключ B

(сервер транслирует только открытые ключи)

Собеседник
Приватный ключ B (dB)
Публичный ключ B (QB = dB * G)
Общий секрет (K = dB * QA)
1

Генерация локальной пары ключей

При первом входе или настройке аккаунта приложение генерирует на устройстве пару асимметричных ключей X25519. Приватный ключ надёжно сохраняется во внутреннем изолированном хранилище ОС (Secure Storage / KeyStore / Keychain), а публичный отправляется в базу данных сервера для обеспечения доступности вашего контакта другим пользователям.

2

Вычисление общего секрета (Shared Secret)

Когда вы открываете чат с пользователем, клиентское приложение автоматически запрашивает публичный ключ собеседника с сервера. Используя его совместно со своим приватным ключом, алгоритм ECDH вычисляет уникальный симметричный ключ (общий секрет). Он никогда не передаётся по сети — обе стороны получают абсолютно одинаковый ключ математическим путём.

3

Симметричное шифрование AES-256-GCM

Полученный общий секрет передается в алгоритм шифрования AES-256 в режиме Galois/Counter Mode. Каждое сообщение шифруется с использованием уникального вектора инициализации (Nonce), что делает невозможным проведение атак на основе повторяющихся шифротекстов.

2. Шифрование и деривация текстовых сообщений

Каждое текстовое сообщение шифруется с генерацией случайного 12-байтового вектора инициализации (IV / Nonce). Режим GCM гарантирует аутентифицированное шифрование (AEAD): к шифротексту добавляется 16-байтовый тег аутентификации (MAC), подтверждающий, что данные не были изменены при транзите через сервер.

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

[Nonce (12 байт)] + [MAC Тег (16 байт)] + [Шифротекст (N байт)] => Кодирование в Base64

Пример реализации алгоритмов шифрования и расшифрования в приложении на Dart с использованием криптографических библиотек:

// Шифрование строки текста на общем ключе
Future<String> encryptMessage(String plainText, SecretKey sharedKey) async {
  final algorithm = AesGcm.with256bits();
  final clearTextBytes = utf8.encode(plainText);
  
  // Генерация случайного вектора инициализации (Nonce)
  final secretBox = await algorithm.encrypt(
    clearTextBytes,
    secretKey: sharedKey,
  );
  
  // Объединяем nonce, mac-тег и зашифрованные байты в один пакет
  final combinedBytes = BytesBuilder()
    ..add(secretBox.nonce)
    ..add(secretBox.mac.bytes)
    ..add(secretBox.cipherText);
    
  return base64Encode(combinedBytes.toBytes());
}

// Дешифрование сообщения на клиенте
Future<String> decryptMessage(String base64Data, SecretKey sharedKey) async {
  final rawData = base64Decode(base64Data);
  if (rawData.length < 28) throw Exception("Пакет данных слишком мал");
  
  final nonce = rawData.sublist(0, 12);
  final mac = rawData.sublist(12, 28);
  final cipherText = rawData.sublist(28);
  
  final algorithm = AesGcm.with256bits();
  final decryptedBytes = await algorithm.decrypt(
    SecretBox(cipherText, nonce: nonce, mac: Mac(mac)),
    secretKey: sharedKey,
  );
  
  return utf8.decode(decryptedBytes);
}

3. Поблочное шифрование медиафайлов (Крипто-стриминг)

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

  1. Генерация ключа файла: Для каждого медиафайла генерируется индивидуальный случайный 256-битный ключ (fileKey). Это позволяет безопасно делиться ключом конкретного файла, не компрометируя общий секрет чата.
  2. Шифрование ключа: Ключ fileKey зашифровывается с помощью AES-GCM на основном общем ключе чата (sharedSecret). Этот зашифрованный ключ прикрепляется к сообщению как поле encrypted_key.
  3. Поблочное чтение и шифрование: Исходный файл считывается потоком частями по 64 КБ. Каждый блок шифруется алгоритмом AES-256-GCM независимо.
  4. Форматирование блоков: К зашифрованным блокам добавляется структура:
    [Длина блока (4 байта)] + [Nonce (12 байт)] + [Зашифрованные данные (64 КБ)] + [Тег аутентификации MAC (16 байт)]
  5. Передача на Google Drive: Зашифрованный поток отправляется напрямую в облачное хранилище через сервер. Сервер имеет доступ только к зашифрованному потоку байтов и не знает ключ fileKey.
Исходный медиафайл (Изображение, Видео, Голосовая заметка)
👇 Разделение на чанки в потоке по 64 КБ
Блок 1 (64 КБ)
🔒 AES-256-GCM (на ключе fileKey)
Длина (4б) + Nonce (12б) + Данные + MAC (16б)
Блок 2 (64 КБ)
🔒 AES-256-GCM (на ключе fileKey)
Длина (4б) + Nonce (12б) + Данные + MAC (16б)
Хвостовой Блок (< 64 КБ)
🔒 AES-256-GCM (на ключе fileKey)
Длина (4б) + Nonce (12б) + Данные + MAC (16б)

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

4. Защита ключей и облачное резервное копирование (Backup)

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

5. Управление сессиями и синхронизация (Multi-Device Sync)

Чепухаграм спроектирован для бесшовной работы на нескольких устройствах одного пользователя. Это требует сложной логики синхронизации сообщений, прочтений и статусов через реалтайм WebSocket-каналы и локальную СУБД (Drift SQLite):

Доставка событий о прочтении (Read Receipts)

При чтении переписки на одном устройстве, состояние непрочитанных сообщений синхронизируется на всех остальных девайсах пользователя с точностью до чата:

Смена мастер-пароля шифрования секретного ключа и отзыв авторизации (Force Logout)

Выход из сессий на других устройствах происходит исключительно при смене мастер-пароля шифрования секретного ключа (или при полном сбросе ключей). Это гарантирует своевременное прекращение доступа к аккаунту при изменении ключевого секрета:

  1. Во время изменения мастер-пароля шифрования приватного ключа сервер определяет идентификатор сессии (session_id) устройства, инициировавшего операцию.
  2. Сервер находит и удаляет все остальные активные сессии этого пользователя из таблицы sessions базы данных.
  3. Для каждой отключенной сессии бэкенд вызывает метод kill_session_socket в менеджере WebSocket-соединений.
  4. На эти устройства отправляется WebSocket-пакет {"type": "session_terminated"}, после чего сокеты принудительно закрываются.
  5. Устройства, получившие данный сигнал, немедленно удаляют локальный файл базы данных сообщений (chat_app.db), токены авторизации, приватный ключ и возвращаются на экран входа.

Безопасность при выходе: При логауте база данных SQLite на компьютере или телефоне полностью стирается на уровне файловой системы. Это исключает возможность физического извлечения переписки с диска устройства после выхода из учётной записи.