Для полного понимания происходящего неплохо было бы быть знакомым с основами криптографии, с принципом работы хеш функций (в данной статье SHA-1, SHA-256), а также с такими протоколами как RSA, AES и Diffie-Hellman (приведены ссылки для более подробного ознакомления).
Оглавление
Предисловие
Здравствуйте, дорогие хабровчане! Я здесь новенький, поэтому не кидайтесь там палками, помидорами и всем прочим (хотя, кидайтесь, мб, полезнее будет). Как один из всадников ноябрь-декабрьского криптографического апокалипсиса, я пришел вам поведать о протоколе, что используется как в секретной переписке с мамой о покупке продуктов, так и в не очень доброжелательных целях.
21 год на дворе. В чем там сейчас чатятся зуммеры, бумеры, думеры, миллениалы и вот эти все касты? Тележка, конечно, тележка. Каждый из нас хочет, чтобы его самые сокровенные секреты, будь то причудливые мемы, переписки со странными субъектами, да и что уж таить, подписки на аниме-каналы, остовались секретами до конца. Но VK же, вроде, удовлетворяет всем нуждам и потребностям, удобно и доступно. Соглашусь, мы в СНГ выросли уже на этой социальной сети, и она нам как родная (а ее, как и тележку, основал Пашенька). Но на данный момент она переживает не лучшие времена, пытаясь подражать всему и вся, добавляя никому ненужный функционал, а также заполняя ленту невероятным количеством рекламы (на каждые 6 постов, 1 рекламный – ужас). Также, бог весть, что там за защита у VK.
В то же время тележка намного проще и чище в плане функционала и рекламы (пока что). Более того, Пашенька позиционирует свой чатек, как несокрушимую и непоколебимую крепость в плане взлома, а сам алгоритм шифрования MTProto выставлен перед всеми на обозрение. Так давайте поговорим о внутреннем устройстве MTProto, разработанного собственноручно командой тележки с точки зрения криптографии.
High-level описание
А дела в алгоритме обстоят довольно запутанно с первого взгляда. Разработчики тележки, самые что ни на есть храбрецы: взять уже готовые протоколы, по типу Signal – не, скучно; создать свой протокол, используя всевозможные известные алгоритмы с добавлением кучи своих фишек и фокусов, чтобы все было еще секретнее и сложнее – прекрасное решение. Так и появился MTProto.
Начать, пожалуй, нужно с описания работы в целом. MTProto – клиент-серверный набор протоколов, служащий для доступа к серверу из клиентского приложения через незащищенное соединение. Этот набор можно разделить на 3 основные части:
-
High-level API and Type language: отвечает как за API запросы и ответы, так и за сериализацию данных.
-
Cryptographic and authorization components: определяет, как приложение (клиент) авторизируется на сервере, а также шифрование сообщений перед отправкой на транспортный уровень.
-
Transport component: определяет, как клиент и сервер обмениваются сообщениями по средствам таких транспортных протоколов как UDP, TCP, HTTP(S), WebSocket и другие.
Итак, как я и сказал, мы остановимся на втором уровне, связанном с криптографией и авторизацией (C&A), и поглядим, как вся кухня устроена. В свою очередь данный уровень можно поделить на 3 модуля:
-
Authorization: этот модуль отвечает за первоначальную авторизацию клиента. Он работает во время первого запуска приложения, чтобы получить ключ авторизации.
-
Secret chat key exchange and rekeying: данный модуль отвечает за установку сессионного общего секретного ключа между клиентами, используемого в сквозном шифровании.
-
Message encryption: модуль-работяга, не покладая рук, шифрует наши сообщения симметричным шифром AES.
Терминология
Начать наше путешествие, думаю, стоит с описания всех фигурирующих величин и терминов. Для удобства в статье большинство из них будут написаны на забугорском языке (лучше выделяются, а также легче яндексятся).
Итак, дамы и господа, наша сегодняшняя терминология:
-
Authorization key (AK, auth_key) – 2048-битный ключ, который создается на этапе пользовательской регистрации по средством алгоритма Diffie-Hellman, а доступ к нему имеет только клиент и сервер. Более того, утверждается, что ключ шифруется на сервере, а ключ к ключу отправляется на другой сервер. Таким образом, получение доступа лишь к одному серверу – недостаточно для взлома.
-
RSA:– 2048-битный закрытый ключ RSA, – 2048-битный открытый ключ, используемые на этапе регистрации и генерации ключа авторизации.
-
Key identifier (auth_key _id) – 64 младших бита хеша (SHA-1) auth_key, которые используются для идентификации конкретного ключа, используемого для шифрования сообщения.
-
Session_id – случайное 64-битное число, генерируемое клиентом с целью различить отдельные сеансы одного пользователя (на телефоне, на ПК несколько окон).
-
Server salt – случайное 64-битное число, меняющееся каждые 30 минут (отдельно для каждой сессии) по запросу сервера. Сообщения должны приниматься лишь с новой солью ( 😀 ), но старые валидны в течение 1800 секунд. Требуется для защиты от атак повторного воспроизведения.
-
Message identifier (msg_id) – 64-битное число, используемое для однозначной идентификации сообщения в сеансе. Идентификаторы сообщений сервера и клиента должны монотонно увеличиваться (в пределах одного сеанса), и указывать приблизительный момент создания сообщения.
-
Internal header – 16-байтовый заголовок, добавляемый перед сообщением и содержащий server salt и session_id.
-
Padding (12-1024 бит) – добавление ничего не значащих данных к информации, нацеленное на повышение криптостойкости.
-
Message key (msg_key) – средние 128 бит хеша (SHA-256) сообщения, которое надо зашифровать (учитывает при расчёте internal header и padding).
-
External header – 24-байтовый заголовок, добавляемый перед зашифрованным сообщением и содержащий auth_key_id и msg_key.
-
Key derivative function (KDF) – функция, формирующая один или несколько секретных ключей на основе секретного значения с помощью псевдослучайной функции (используется SHA-256).
Фух, тяжело, понимаю, прямо как на матане, когда на тебя вываливают гору определений, но крепитесь. Не забудьте открыть в дополнительном окне этот список, чтобы подсмотреть, что за что отвечает (людям с телефона RIP – мотайте).
Клиент-серверное шифрование
Давайте-ка взглянем на схему этого криптографического чуда:
Выглядит не так уж и сложно. Ну что тут: обычный Diffie-Hellman, SHA-256, AES – да и все, делов-то. Но давайте все же немного приоткроем завесу тайны и попробуем разобраться что да как.
В общих словах работа алгоритма такова:
-
Собирается пакет для шифрования, состоящий из server salt, session_id, самого сообщения (в него включены время, длина и порядковый номер, которые проверяются на стороне получателя) и padding.
-
Далее, находится msg_key, 128 средних бита хеша (SHA-256) от сообщения с добавлением 32-байтового фрагмента auth_key.
-
Auth_key в комбинации с ново найденным msg_key определяет при помощи KDF 256-битный aes_key и 256-битный начальный вектор aes_iv.
-
Далее найденные значения aes_key и aes_iv используются в алгоритме AES IGE для шифрования сообщения.
-
В самом конце собирается пакет, состоящий из external header, а также зашифрованного сообщения.
Создание auth_key
Начнем с самой важной состовляющей, а в то же время с самой замороченной и интересной, с создания auth_key. В основном здесь используется RSA, SHA-1, AES и Diffie-Hellman, а также добавлены некоторые тонкости для еще большей надежности и секретности. Привожу схему (не пугайтесь):
Поехали по порядку:
-
C: генерирует случайное 128-битное число (идентифицирует C в рамках этого процесса) и отправляет его.
-
S: генерирует свое случайное 128-битное число(далее включены во все сообщения как в зашифрованном виде, так и в обычном), создает натуральное число, являющееся произведением простых чисел и. После, отправляет , где – отпечаток RSA ключа равный 64 нижним битам хеша (SHA-1) известных (публичный ключ RSA). В свою очередь S хранит (закрытые ключи RSA) для дешифровки.
-
C: раскладывает на простые множители (реализовано для защиты от DoS атак), выбирает публичный ключ , отвечающий одному из отпечатков , генерирует еще одно случайное 256-битное число , которое вместе с используется для получения эфемерного ключа и начального вектора для последующей шифровки сообщения с помощью AES IGE. Посылает , где , а также введено обозначение – шифрование с применением .
-
S: выбирает параметры для алгоритма Diffie-Hellman, рассчитывает для случайного 2048-битового числа , вычисляет . Посылает , где (— серверное время).
-
C: вычисляет , рассчитывает для случайного 2048-битового числа b, проводит советующие проверки для (об этом чуть дальше), получает auth_key: . Посылает , где
, если это первая попытка посылки данного сообщения, , если S позже запросит для повторного согласования auth_key в том же сеансе путем генерации нового (такая ситуация может возникнуть при проверке уникальности, выполненной в конце). -
S: получает auth_key: , затем удостоверяется что, полуенный ключ уникальный, сравнивая его хеш с хешами других auth_keys. Если хеш уникален, то S отправляет подтверждение , в противном случае S отправляет сообщение об ошибке и процесс возвращается к стадии 4.
В течение работы этого алгоритма необходимо делать следующие проверки:
-
C должен проверить: и являются простыми числами, , порождает циклическую подгруппу по простому основанию.
-
C и S должны верифицировать, что . Также телеграмм рекомендует, чтобы обе стороны проверяли следующее:.
-
C и S должны проверять, что msg_key равен 128 средним битам хеша (SHA-256) расшифрованных данных с добавлением 32-байтового фрагмента auth_key и что msg_id четное для сообщений от C, и нечетное в противном случае.
-
У C и S должны быть сохранены идентификаторы msg_id последних N сообщений. Если сообщение приходит с идентификатором меньшим или равным тем, что хранятся – сообщение игнорируется. В противном случае новый msg_id сохраняется, и если требуется, самый старый затирается.
Так-так, самое мудреное и сложное позади, здесь можно выдохнуть. На самом деле это все не так сложно, если позалипать в схему и вчитаться в ход алгоритма.
Немного про AES IGE
Вы могли заметить, как при создании auth_key, так и в основном алгоритме MTProto учувствует некое шифрование AES IGE. Это всеми любимое AES шифрование, работающее в Infinite Garble Extension режиме. Пару слов про данный режим:
IGE режим задается следующим цепным равенством:
где – блок шифротекста, – блок сообщения, которое необходимо закодировать, – обозначение манипуляций, производимых над блоком сообщения сксоренным с блоком шифротекста предыдущей итерации во время выполнения блочного шифрование (в нашем случае AES) с ключом , – индекс, пробегающий от 1 до (количество текстовых блоков, на которое разбито сообщение). Для запуска сего механизма требуется начальные значения и , которые могут быть получены из начального вектора .
Получается, что разработчики тележки вместо того, чтобы взять какой-либо существующий режим работы для блочных шифров, решили изобрести свой велосипед с начальным вектором и ключами. Как утверждают сами разработчики, данное решение усиливает стойкость, а также тот факт, что ключ зависит от содержимого сообщения, сводит на нет блочно-адаптивные атаки.
Секретные чаты и сквозное шифрование
Окей, вроде все секретно, все отлично. Но это все под защитой покуда у злоумышленника нет доступа до серверов тележки, так как на них хранится вся зашифрованная переписка вместе с ключами для того, чтобы иметь доступ в нескольких сессиях. Так-так, а вдруг я захочу обсудить с другом кто лучший из BTS, но не хотелось бы, чтобы это знали другие. В такой ситуации есть решение – секретные чаты. Давайте перейдем к рассмотрению сквозного шифрования в тележке.
Наше желание: только пользователи, которые инициируют общение, имеют доступ к переписке, и никто больше, при том только в одной сессии. Для этого нам требуется, чтобы у каждого пользователя были ключи, дающие возможность шифровки и дешифровки сообщений.
Схема шифрования почти идентична с предыдущей:
Опять же, в общих словах, по очереди происходит 2 идентичных шифрования с разными ключами SK и AK. Нам требуется добыть SK да так, чтобы никто и никогда не знал его. В этом нам опять же поможет всеми любимый алгоритм DH.
Схема получения SK перед вами (довольно знакомая, не правда ли):
Кратко о процессе:
-
A: получает параметры от S, генерирует (для определения текущей сессии), рассчитывает Отправляет , где – запрос на инициализацию секретного чата от клиента A клиенту B.
-
B: при согласии на инициализацию секретного чата, получает параметры от S, рассчитываета также и его 64-битный хеш (SHA1). Отправляет .
-
A: рассчитывает и сверяет хеш (для удостоверения правильной работы клиентского приложения).
Собственно все. Теперь сообщение сначала шифруется с использованием ключа SK и алгоритма, расписанного выше, а потом результат проходит второй круг шифрования с использованием AK и отправляется через сервер другому клиенту.
Rekeying (смена ключа шифрования)
Посидели разработчики тележки, посмотрели на все, что они наворотили, почесали репу, да решили, что как-то это все не слишком секретно, ненадежно. А вдруг кто-то получит секретный ключ и сможет расшифровать сообщения. Недолго думая, они взяли да реализовали алгоритм смены ключей. По их задумке секретные ключи, используемые в сквозном шифровании, сменяются каждые 100 сообщений или же каждую неделю. Старые ключи должны быть уничтожены и более не использоваться. Думаю, в третий раз разъяснение алгоритма DH – это уже перебор, поэтому просто приведу схему:
На данном этапе, разработчики почувствовали себя в безопасности и решили остановиться.
Заключение
Фух, смотрите, сколько Пашенька и его команда вложила души в секретность тележки, грех не пользоваться. Хотя, криптоаналитики и разработчики были в полном ужасе, увидав кашу из всех этих алгоритмов и своих тонкостей (в данной статье опущено множество технических подробностей, например, расчеты хэшей, а там все очень и очень запутанно).
Теперь запросы правительств о выдаче ключей шифрования звучат уж слишком смешно. Ну а нам, простым смертным, со спокойной душой можно пользоваться всеми нами любимой тележкой, покуда квантовые компьютеры не пришли и не раздали нам подзатыльники за наши математические фокусы.
Надеюсь, мне удалось донести основы того, как функционирует MTProto и стало немного яснее, как устроено шифрование в мессенджерах (устройство общее). А вам спасибо за ваше внимание и приглашаю в комментарии для дальнейшего обсуждения. Буду рад, если кто-то укажет неточности, ежели таковые запреметит.
P.S. И помните, когда вы отправляете одну единственную скобку, реагируя на какую-то новость, вы заставляете ваш бедный телефон и сервера тележки вкалывать, чтобы это все было секретно.
Литература и ссылки на почитать
К сожалению или к счастью, все на английском.