# BS-Dec-Key: Анализ и Реализация Клиента Этот документ предоставляет детальное техническое описание процесса подключения к серверу, который является модифицированной версией Project Colette V53, использующей криптографическую схему от **BSL-V53**. Здесь разбирается финальная, рабочая версия handshake, структура пакетов и логика обмена сообщениями. ## [*] Основные Концепции Протокол обмена данными является кастомным, поверх стандартного TCP. Шифрование построено на базе криптографической библиотеки **NaCl** и использует смешанную, нестандартную схему. - **Асимметричное шифрование**: `Curve25519` для вычисления общего секрета по алгоритму Диффи-Хеллмана (ECDH). - **Симметричное шифрование**: `XSalsa20-Poly1305` для шифрования сообщений после вычисления общего секрета. - **Порядок пакетов**: В отличие от многих протоколов, здесь порядок не `ClientHello` -> `ServerHello` -> `LoginMessage`, а `ClientHello` -> `LoginMessage` -> `ServerHello` -> `LoginOk`. ## [!] Пошаговый Разбор Процесса Подключения Процесс подключения от инициации до полного установления зашифрованной сессии включает в себя обмен четырьмя ключевыми пакетами в специфическом порядке. --- ### **Шаг 1: `ClientHello` (ID: 10100)** - **Направление**: Клиент -> Сервер - **Шифрование**: Отсутствует Это самый первый пакет, который клиент отправляет после установки TCP-соединения. Его структура критически важна и должна точно соответствовать ожиданиям сервера (6 целочисленных полей и пустая строка), иначе сервер просто разорвет соединение. --- ### **Шаг 2: `LoginMessage` (ID: 10101)** - **Направление**: Клиент -> Сервер - **Шифрование**: **Симметричное (`SecretBox`)**, но с ключом, полученным асимметрично. Это ключевой и самый сложный пакет, который отправляется **до** получения `ServerHello`. #### **Подготовка на стороне клиента (перед отправкой):** 1. **Обмен ключами и вычисление секрета**: - Клиент использует статичный публичный ключ сервера (`server_public_key`), заранее известный из анализа Frida-скрипта. - Клиент генерирует свою временную пару ключей (`client_public_key` и `client_private_key`). - Клиент вычисляет **общий секрет (`s`)** с помощью ECDH. Этот `s` используется **только для шифрования/расшифровки `LoginMessage` и `LoginOk`**. 2. **Формирование Payload**: - Клиент генерирует свой собственный **`RNonce`** (24 байта). - Внутренние данные (`LoginData`) формируются в `ByteStream`. Они включают в себя ID аккаунта (0-1 для нового), версию клиента (`47.365.2`) и множество полей с информацией об устройстве, включая валидные по формату идентификаторы (UUID, HEX-строки). - Payload для шифрования собирается как `RNonce` + `LoginData`. 3. **Шифрование**: - **Ключ**: Используется `s`, вычисленный на шаге 1. - **Nonce**: Вычисляется как `hash(client_pk + server_pk)`. - **Процесс**: `(RNonce + LoginData)` шифруется с помощью `SecretBox(s).encrypt(...)`. #### **Структура и отправка пакета:** Финальный пакет `10101` состоит из: - **Публичный ключ клиента** (32 байта, в открытом виде). - **Зашифрованная полезная нагрузка**. --- ### **Шаг 3: `ServerHello` (ID: 20100)** - **Направление**: Сервер -> Клиент - **Шифрование**: Отсутствует Получив и успешно расшифровав `LoginMessage`, сервер присылает этот пакет в открытом виде. Он содержит **серверный Nonce (`SNonce`)**, который будет использоваться для дальнейшей связи. --- ### **Шаг 4: `LoginOk` (ID: 20104)** - **Направление**: Сервер -> Клиент - **Шифрование**: Симметричное (`SecretBox`) Это финальное подтверждение от сервера. - **Ключ**: Сервер использует тот же самый `s`, который он вычислил ранее. - **Nonce**: Сервер вычисляет nonce как `hash(RNonce + client_pk + server_pk)`. - **Содержимое**: Внутри расшифрованного пакета находится **второй, настоящий ключ сессии (`session_key`)**, который будет использоваться для шифрования всех последующих сообщений (кроме handshake). Успешная расшифровка этого пакета означает, что аккаунт создан и сессия полностью установлена. Разрыв соединения сервером сразу после отправки `LoginOk` является **нормальным поведением** для простого тестового клиента, который не продолжает общение (например, не шлет `KeepAlive`).