MTProto

MTProto

Unknown

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

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

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

  • компонент высокого уровня (язык запроса API): определяет метод, посредством которого запросы и ответы API конвертируются в двоичные сообщения.
  • криптографический слой (слой авторизации): определяет метод, которым шифруются сообщения перед тем как они будут переданы посредством протокола доставки.
  • компонент доставки: определяет для клиента и сервера метод передачи сообщений через некий другой существующий сетевой протокол (такой как http, https, tcp, udp).

Каждое текстовое сообщение, которое нужно зашифровать через MTProto, всегда содержит следующие данные, которые проверяются расшифровкой, чтобы сделать систему устойчивой против известных проблем с компонентами: server salt (соль сервера) (64-битная)

  • session id (идентификатор сессии)
  • message sequence number (порядковый номер сообщения)
  • message length (длина сообщения)
  • time (время)

Краткий обзор компонентов

Компонент высокого уровня (язык запроса RPC/API)

С точки зрения компонента высокого уровня, клиент и сервер обмениваются сообщениями внутри сессии. Сессия привязана к приложению, а не к конкретному http/https/tcp соединению. Дополнительно, каждая сессия прикреплена к user key ID, которым собственно и завершается авторизация.

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

Есть несколько типов сообщений:

  • RPC вызовы (от клиента к серверу): обращается к методам API
  • RPC ответы (от сервера к клиенту): результаты RPC вызовов
  • подтверждение получения сообщения (или, точнее, уведомление о статусе группы сообщений)
  • запрос статуса сообщения
  • сообщение из нескольких частей или контейнер (контейнер, который содержит несколько сообщений, который должен послать несколько RPC вызовов за раз посредством соединения HTTP, например; также, контейнер может поддерживать gzip).

С точки зрения нижних уровней протокола, сообщение является потоком двоичных данных, выровненных по границе 4- или 16- байт.

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

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

Все числа записываются в кодировке little endian. Однако очень большие числа (2048-битные) использованные в RSA и DH записываются в формате big endian, т.к. это делает библиотека OpenSSL.

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

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

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

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

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

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

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

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

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

Транспорт (передача)

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

  • HTTP
  • TCP
  • UDP

Мы исследуем первые два типа.

Передача по HTTP

Осуществляется через HTTP 1.1 (постоянное HTTP-соединение), работает под традиционным TCP Port 80. HTTPS не используется, вместо этого используется упомянутый выше метод шифрования.

Соединение HTTP прикреплено к сессии (или скорее к идентификатору сессии+ключа), указанной в последнем полученном запросе юзера; обычно сессия одна и та же во всех запросах, но коварные HTTP прокси могут исказить это. Сервер может не вернуть сообщение в HTTP соединение, если оно не принадлежит к одной и той же сессии, и если не наступила очередь сервера (когда от клиента был получен HTTP запрос, на который ещё не был отправлен ответ).

Общий механизм следующий: клиент открывает одно или более постоянных HTTP-соединений с сервером; если должны быть отправлены одно или более сообщений, они объединяются под одним payload’ом, после которого следует POST запрос к URL/api к которому payload передаётся в виде данных. Кроме того, Content-LengthKeepalive, и Host являются действующими HTTP заголовками.

Получая запрос, сервер может или подождать некоторое время (если запрос требует ответа после короткого тайм-аута) или немедленно вернуть макет ответа (dummy response) (лишь подтверждая получение контейнера). В любом случае, ответ может содержать любое количество сообщений. Сервер может одновременно отправлять любые другие сообщения, которые содержит сессия.

Дополнительно, существует специальная очередь ожидающих RPC запросов (действующая только для HTTP соединений), которая передаёт с максимальной задержкой Т. Если у сервера есть сообщения для сессии, они возвращаются немедленно, в противном случае, включается режим ожидания до того времени, пока у сервера есть сообщение для клиента, или пока не пройдёт Т секунд. Если ничего не происходит за Т секунд, возвращается макет ответа.

Если серверу нужно послать сообщение клиенту, он проверяет HTTP соединение, которое принадлежит к нужной сессии и находится в состоянии «ответ на HTTP запрос» (включая очередь запросов), после чего сообщение добавляется к контейнеру ответа и отправляется юзеру. В типичном случае, есть некое дополнительное время ожидания (50 миллисекунд) на случай, что у сервера скоро будет больше сообщений для сессии.

Если нет подходящего доступного HTTP соединения, сообщения помещаются в очередь отправки текущей сессии. Однако они найдут свой путь до того как получение будет прямо или косвенно подтверждено сервером. Для HTTP протокола, отправка следующей очереди в том же HTTP соединении считается подтверждением (с этого момента HTTP протокол больше не требует, чтобы подтверждение было отправлено); в других случаях, клиент должен отправить точное подтверждение в течение допустимого времени (оно может быть добавлено к контейнеру для следующего запроса).

ВАЖНО. Если подтверждение не пришло вовремя, сообщение может быть отправлено заново (возможно, в другом контейнере). Объекты должны быть автономно подготовлены к этому и должны сохранить (записать) идентификаторы самых последних принятых сообщений (и игнорировать дубликаты, а не повторять действия). Чтобы не хранить идентификаторы вечно, существуют специальные сообщения-«сборщики мусора», которые пользуются однообразием идентификаторов сообещний.

Если отправленная очередь переполняется или если сообщения остаются в очереди дольше 10 минут, сервер забывает их (или отправляет в swap, ничего особенного здесь делать не требуется). Это может произойти даже быстрее, если у сервера закончилось буферное пространство (например, потому что серьёзные проблемы с сетью привели к большому количеству разорванных соединений).

TCP-транспорт

Очень схожа с передачей HTTP. Может так же быть осуществлена посредством порта 80 (чтобы проникнуть через все фаерволы) и даже использовать те же сервера IP адресов. В этой ситуации, сервер понимает, какой протокол нужно использовать — HTTP или TCP — основываясь на первых четырёх входящих байтах (для HTTP это POST).

Когда создано TCP-соединение, оно приписывается к сессии (и ключу авторизации), переданной в первом сообщении юзера, и в дальнейшем используется исключительно для этой сессии (составные механизмы не разрешены).

Если payload (пакет) нужно передать от сервера к клиенту или от клиента к серверу, это выражается таким образом: 4 байта длины добавляются впереди (содержащие в себе длину, порядковый номер и CRC32; всегда делятся на 4) и 4 байта с порядковым номером пакета внутри TCP-соединения (первый отправленный пакет нумеруется как 0, следующий — как 1, и т.д.) и 4 CRC32 байта в конце (длина, порядковый номер, и payload вместе).

Есть сокращённая версия этого же протокола: если клиент отправляет 0xEF как первый байт (важно: только перед самым первым пакетом данных), то тогда длина пакета кодируется одним байтом (0x01..0x7E = длина данных разделённая/ делящаяся на/ кратная 4; или 0x7F после которого следуют 3 байта длины (little endian) кратным 4) после чего следуют собственно данные (порядковый номер и CRC32 не добавляется). В этом случае ответы сервера выглядят точно так же (сервер не отправляет 0xEF как первый байт).

В случае, если требуется выравнивание 4-байтовых данных, может быть использована промежуточная версия оригинального протокола: если клиент отправляет 0xEEEEEEEE как первый int (четыре байта), то длина пакета зашифрована всегда четырьмя байтами как в оригинальной версии, но порядковый номер и CRC32 опускаются, таким образом уменьшая итоговый/общий размер пакета на 8 байт.

Полная, промежуточная и сокращённая версии протокола поддерживаются для быстрого подтверждения. В этом случае клиент устанавливает бит длины наивысшего порядка в пакет запроса, и сервер отвечает специальными четырьмя байтами в виде отдельного пакета. Это 32 бита SHA1 высшего порядка зашифрованной части пакета, с самым важным/значимым битом, установленным, чтобы пояснить, что это не длина обыкновенного пакета ответа сервера; если используется упрощённая версия, для этих четырёх байт применяется bswap.

Не существует неявного/скрытого подтверждения для TCP-передачи: все сообщения должны быть подтверждены точно. Чаще всего подтверждения помещают в контейнер с следующим запросом или ответом, если он передаётся в упрощённом порядке. Например, это почти всегда происходит с сообщениями клиента, содержащими RPC-запросы: подтверждение обычно приходит вместе с RPC-ответом.

В случае ошибки, сервер может отправить пакет в котором payload состоит из 4 байт, которые являются кодом ошибки. Например, Код Ошибки 403 соответствует ситуациям, когда сответствующая ошибка HTTP возвращена HTTP-протоколом.

Подробное описание мобильного протокола MTProto

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

Ключ юзера вместе с ключом сообщения определяет актуальный 256-битный ключ и 256-битный вектор инициализации, который шифрует сообщение, используя AES-256 шифрование с расширением неопределённого искажения (infinite garble extension, IGE). Обратите внимание, что часть сообщения, которая должна быть зашифрована, содержит переменные данные (сессию, ID сообщения, порядковый номер, соль сервера), которые явно оказывают влияние на ключ сообщения (и таким образом на ключ AES и iv). Ключ сообщения определяется 128 битами нижнего порядка от SHA1 тела сообщения (включая сессию, ID сообщения, и т. д.) Составные сообщения шифруются как одно сообщение.

MTProto

Терминология

Ключ авторизации

2048-битный ключ, которым обмениваются девайс клиента и сервер, созданный непосредственно во время регистрации юзера на устройстве клиента, чтобы обмениваться ключами Диффи-Хеллмана, и никогда не передаваемый через сеть. Каждый ключ авторизации существует только для конкретного пользователя. Ничто не мешает юзеру иметь несколько ключей (которые согласовываются с «перманентными сессиями» на разных девайсах), некоторые из них могут быть заблокированы навсегда, если девайс утерян.

Ключ сервера

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

Идентификатор ключа

64 бита нижнего порядка хэша SHA1 ключа авторизации используется, чтобы показать, какой именно ключ был использован для шифрования сообщения. Ключи должны уникально определяться 64-мя битами нижнего порядка их SHA1, и в случае коллизии/столкновения, ключ авторизации генерируется заново. Нулевой идентификатор ключа (zero key identifier) означает, что шифрование не было использовано, что разрешено для ограниченного набора типов сообщений, используемых во время регистрации для генерации ключа авторизации, основанного на обмене Диффи-Хеллмана.

Сессия

Рандомное 64-битное число, сгенерированное клиентом для того, чтобы различать индивидуальные сессии (например, между разными инстанциями приложения, созданными с помощью одного и того же ключа авторизации). Сессия вместе с идентификатором ключа согласовывается с инстанцией приложения. Сервер может поддерживать состояние сессии. Ни в коем случае сообщение, предназначенное для одной сессии, не может быть отправлено в другой сессии. Сервер может в одностороннем порядке забыть любые сессии клиента; клиенты должны быть способны справиться с этим.

Соль сервера (Server Salt)

Рандомное 64-битное число, периодически (например, каждые 24 часа) изменяемое (отдельно для каждой сессии) по запросу сервера. Все последующие сообщения должны содержать новый salt (хотя, сообщения со старым salt’ом принимаются на протяжении следующих 300 секунд). Предназначается для защиты против атак повторного воспроизведения, и для определённых уловок/трюков, связанных с регулировкой часов клиента к моменту в отдалённом будущем.

Идентификатор сообщения (msg_id)

Зависимое от времени 64-битное число, используемое для того, чтобы уникально идентифицировать сообщение внутри сессии. Идентификаторы сообщения клиента кратны четырём (делятся на 4), остаток от деления идентификатора сообщения сервера на 4 приравнивается к 1, если сообщение является ответом на сообщение клиента и к трём в остальных случаях. Идентификаторы сообщения клиента должны увеличиваться монотонно (внутри одной сессии), так же как идентификаторы сообщений сервера, и должны примерно равняться unixtime*2^32. Таким образом, идентификатор сообщения указывает на приблизительный момент времени, в который сообщение было создано. Сообщение отклоняется через 300 секунд после того, как оно было создано, или за 30 секунд до того как оно будет создано (это необходимо для защиты против атак повторного воспроизведения). В этой ситуации, оно должно быть отправлено заново с другим идентификатором (или посещено в контейнер с более высоким идентификатором). Идентификатор контейнера сообщений обязательно должен быть больше, чем идентификатор вложенных в него сообщений.

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

Сообщение, связанное с контентом

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

Порядковый номер сообщения (msg_seqno)

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

Ключ сообщения

128 бит нижнего порядка хэша SHA1 части сообщения, которая будет зашифрована (включая внутренний заголовок и исключая байты выравнивания данных).

Внутренний (криптографический) заголовок

Заголовок (16 байт), добавляемый перед сообщением или контейнером до того, как они все вместе будут зашифрованы. Состоит из соли сервера (64 бита) и сессии (64 бита).

Внешний (криптографический) заголовок

Заголовок (24 байта), добавляемый перед зашифрованным сообщением или контейнером. Состоит из идентификатора ключа (64 бита) и ключа сообщения (128 бит).

Payload (полезная нагрузка)

Внешний заголовок + зашифрованное сообщение или контейнер.

Определение ключа AES и вектора инициализации

2048-битный ключ авторизации (auth_key) и 128-битный ключ сообщения (msg_key) используются для вычисления 256-битного ключа AES (aes_key) и 256-битного вектора инициализации (aes_iv), которые в дальнейшем используются, чтобы зашифровать часть сообщения, которая должна быть зашифрована (то есть всё за исключением внешнего заголовка, который добавляется позднее) с AES-256 в режиме расширения неопределённого искажения (infinite garble extension, IGE).

Алгоритм для вычисления aes_key и aes_iv из auth_key and msg_key таков:

sha1_a = SHA1 (msg_key + substr (auth_key, x, 32));

sha1_b = SHA1 (substr (auth_key, 32+x, 16) + msg_key + substr (auth_key, 48+x, 16));

sha1_с = SHA1 (substr (auth_key, 64+x, 32) + msg_key);

sha1_d = SHA1 (msg_key + substr (auth_key, 96+x, 32));

aes_key = substr (sha1_a, 0, 8) + substr (sha1_b, 8, 12) + substr (sha1_c, 4, 12);

aes_iv = substr (sha1_a, 8, 12) + substr (sha1_b, 0, 8) + substr (sha1_c, 16, 4) + substr (sha1_d, 0, 8);

где x = 0 для сообщений передаваемых от клиента к серверу и x = 8 для сообщений от сервера клиенту.

1024 бита нижнего порядка auth_key не включены в вычисление. Они могут (вместе с оставшимися битами или отдельно) использоваться на девайсе клиента для шифрования локальной копии данных, полученных от сервера. 512 бит нижнего порядка auth_key не хранятся на сервере; следовательно, если девайс клиента использует их, чтобы зашифровать локальные данные, и если юзер теряет ключ или пароль, расшифровка локальных данных невозможна (даже если могут быть получены данные с сервера).

Когда AES используется для шифровки блока данных длиной не делимой по 16 байт, данные подбиваются рандомными байтами до минимальной длины, делимой по 16 байт, непосредственно перед тем как будут зашифрованы.

Важные тесты

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

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

Дополнительно, значения msg_id, относящиеся ко времени более 30 секунд в будущем и более 300 секунд в прошлом, игнорируются. Это особенно важно для сервера. Для клиента это также будет полезным (для защиты от атаки повторного воспроизведения), но только если он его настройки времени точны (например, если его время было синхронизировано с временем сервера).

Определённые сервисные сообщения «от клиента к серверу», содержащие данные, отправленные клиентом серверу (например, msg_id последнего запроса клиента) могут, тем не менее, быть обработаны на/в клиенте даже если время «неправильное». Это особенно верно для сообщений, которые меняют Server Salt и уведомлений о неправильных настройках времени у клиента.

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

Юзерам, заботящимся о безопасности, может быть предложено защитить паролем ключ авторизации — примерно таким же способом как в ssh. Это достигается добавлением SHA1 ключа впереди ключа, после чего вся строка шифруется с использованием AES в режиме CBC и ключа, равного юзерскому (текстовому) паролю. Когда юзер вводит пароль, сохранённый защищённый пароль расшифровывается и проверяется сравнением с SHA1. С точки зрения юзера, это практически то же самое, что и использования пароля вебсайта или приложения.

Незашифрованные сообщения

Специальные только текстовые сообщения могут быть использованы для создания ключа авторизации, также как для выполнения синхронизации времени. Они начинаются с auth_key_id = 0 (64 бита), что означает что здесь нет auth_key. За этим следует непосредственно тело сообщения в сериализованном формате без внутреннего и внешнего заголовка. Идентификатор сообщения (64 бита) и длина тела в байтах (32 байта) добавляются до тела сообщения.

Только очень ограниченное количество сообщений определённых типов могут быть переданы как только текстовые.

Схематическое представление сообщений

Зашифрованное сообщение

- auth_key_id = int64

- msg_key = int128

- encrypted_data = байты

  • auth_key_id — идентификатор ключа
  • msg_key — ключ сообщения
  • encrypted_data — зашифрованные данные

Зашифрованное сообщение: encrypted_data

Содержит шифротекст для следующих данных:

- salt = int64

- session_id = int64

- message_id = int64

- seq_no = int32

- message_data_length = int32

- message_data = байты

- padding 0..15 = байты

  • salt — сервер salt (соль сервера)
  • session_id — сессия
  • message_id — идентификатор сообщения
  • seq_no — порядковый номер сообщения
  • message_data_length — длина данных сообщения
  • message_data — данные сообщения

Незашифрованное сообщение

- auth_key_id = 0 = int64

- message_id = int64

- message_data_length = int32

- message_data = байты

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

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

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