Определение ключа 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 имеет чётный результат для сообщений от клиента к серверу, и нечётный — для сообщений от сервера к клиенту.

[Примечание переводчика: имеется в виду бит чётности (https://ru.wikipedia.org/wiki/Бит_чётности). Вычисляется сложением по модулю 2 (https://ru.wikipedia.org/wiki/Сложение_по_модулю_2), результат 0 считается чётным, результат 1 — нечётным.]

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

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

Определённые сервисные сообщения «от клиента к серверу», содержащие данные, отправленные клиентом серверу (например, msg_id последнего запроса клиента) могут, тем не менее, быть обработаны на/в клиенте даже если время «неправильное». Это особенно верно для сообщений, которые меняют сервер-salt и уведомлений о неправильных настройках времени у клиента. См. «Мобильный протокол: сервисные сообщения» (https://core.telegram.org/mtproto/service_messages).


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: