Мобильный протокол MVSy

Разработчикам клиентов необходимо соблюдать требования безопасности.

Связанные статьи

  • Мобильный протокол: подробное описание

  • Создание ключа авторизации

  • Создание ключа авторизации: пример

  • Мобильный протокол: служебные сообщения

  • Мобильный протокол: служебные сообщения о сообщениях

  • Сериализация двоичных данных

  • Язык TL

  • Схема TL протокола MVSy

  • Сквозное шифрование, секретные чаты

  • Схема TL для секретных чатов

  • Требования безопасности к разработчикам клиентов


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

  • Секретные чаты, сквозное шифрование
  • Звонки со сквозным шифрованием

Общее описание

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

Протокол делится на три практически независимые части:

  • Верхний уровень (язык запросов к API): определяет, как запросы и ответы превращаются в двоичные сообщения.
  • Криптографический слой (авторизация): определяет, как сообщения шифруются перед передачей через транспортный протокол.
  • Транспортная часть: определяет, как клиент и сервер передают сообщения поверх существующих сетевых протоколов — HTTP, HTTPS, WS, WSS, TCP, UDP.
Схема протокола MVSy 1.0

Наши клиенты используют MVSy 1.0, описанный в этой статье.

Краткое описание частей

Верхний уровень (язык RPC-запросов, API)

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

К серверу может быть открыто несколько соединений; сообщения идут в обе стороны по любому из них. Ответ не обязан вернуться по тому же соединению, по которому пришёл запрос, хотя чаще всего так и происходит; но ни при каких условиях сообщение не вернётся по соединению чужой сессии. При использовании UDP ответ может прийти с другого IP-адреса, чем тот, куда уходил запрос.

Сообщения бывают нескольких видов:

  • RPC-вызовы (от клиента к серверу): обращения к методам API
  • RPC-ответы (от сервера к клиенту): результаты вызовов
  • Подтверждение получения — точнее, уведомление о состоянии набора сообщений
  • Запрос состояния сообщения
  • Составное сообщение or контейнер (контейнер с несколькими сообщениями; нужен, например, чтобы отправить несколько вызовов разом по одному соединению; контейнер может быть сжат gzip).

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

Каждое сообщение — отдельное или внутри контейнера — состоит из идентификатора сообщения (64 бита, см. ниже), порядкового номера сообщения в сессии (32 бита), длины (тела сообщения в байтах, 32 бита) и тела (любого размера, кратного 4 байтам). Кроме того, при отправке контейнера или одиночного сообщения сверху добавляется внутренний заголовок , затем всё сообщение шифруется, и сверху помещается внешний заголовок — 64-битный идентификатор ключа и 128-битный ключ сообщения).

A тело сообщения обычно состоит из 32-битного типа сообщения и следующих за ним параметров, зависящих от типа. В частности, каждой RPC-функции соответствует свой тип сообщения.

Все числа записываются в порядке little endian. Однако очень большие числа (2048 бит и pq, p, q больше), используемые в RSA и обмене Диффи — Хеллмана, записываются в big endian — так их пишет библиотека OpenSSL.

Авторизация и шифрование

Перед передачей по сети сообщение — одиночное или составное — шифруется, и сверху добавляется внешний заголовок , а именно 64-битный идентификатор ключа (однозначно определяющий ключ авторизации для сервера, а также пользователя) и 128-битный ключ сообщения. Ключ пользователя вместе с ключом сообщения задаёт настоящий 256-битный ключ, которым сообщение и шифруется алгоритмом AES-256. Начало шифруемого сообщения содержит переменные данные — сессию, идентификатор сообщения, порядковый номер, серверную соль, — и они влияют на ключ сообщения, а значит и на ключ AES с вектором инициализации. Ключ сообщения — это средние 128 бит SHA-256 от тела сообщения вместе с выравнивающими байтами, к которому спереди приписаны 32 байта из ключа авторизации. Составные сообщения шифруются как одно.

Техническое описание — в статье «Мобильный протокол: подробное описание».

Первое, что делает клиент, — создаёт ключ авторизации. Обычно он вырабатывается при первом запуске и почти никогда не меняется.

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

Синхронизация времени

Если время клиента заметно расходится с серверным, сервер может начать игнорировать его сообщения — и наоборот, — потому что идентификатор сообщения тесно связан со временем создания. В этом случае сервер присылает клиенту особое сообщение с правильным временем и 128-битной солью: либо той, что клиент явно запросил, либо равной ключу последнего сообщения, полученного от клиента в текущей сессии. Это сообщение может идти первым в контейнере с другими, если расхождение уже значительное, но ещё не приводит к отбрасыванию сообщений.

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

Если поправку не учесть, клиенту придётся создать новую сессию, чтобы идентификаторы сообщений оставались монотонными.

Транспорт MVSy

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

  • Сокращённый
  • Промежуточный
  • Промежуточный с выравниванием
  • Полный

Сервер различает эти протоколы — и отличает их от HTTP — по заголовку. Дополнительно доступны следующие возможности транспорта:

  • Быстрое подтверждение
  • Ошибки транспорта
  • Обфускация транспорта

Пример реализации этих протоколов есть в adlib .

Транспорт

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

  • TCP
  • WebSocket
  • WebSocket поверх HTTPS
  • HTTP
  • HTTPS
  • UDP

(Разберём только первые пять.)

Итого

Если сопоставить с моделью ISO/OSI: