Мобильный протокол: подробное описание
Рекомендуем вам сначала ознакомиться с техническим FAQ.
Прежде чем сообщение (или составное сообщение / сообщение из нескольких частей) будет передано по сети с использованием транспортного протокола,оно зашифровывается определённым образом, и вверху сообщения добавляется внешний заголовок, который представляет собой: 64-битный идентификатор ключа (который уникально идентифицирует ключ авторизации для сервера,а также для юзера) и 128-битный ключ сообщения.
Ключ юзера вместе с ключом сообщения определяет актуальный (текущий) 256-битный ключ и 256-битный вектор инициализации, который шифрует сообщение, используя AES-256 шифрование с расширением неопределённого искажения (infinite garble extension, IGE).
Обратите внимание, что часть сообщения, которая должна быть зашифрована, содержит переменные данные (сессию, ID сообщения, порядковый номер, соль сервера), которые явно оказывают влияние на ключ сообщения (и таким образом на ключ AES и iv). Ключ сообщения определяется 128 битами нижнего порядка от SHA1 тела сообщения (включая сессию, ID сообщения, и т. д.) Составные сообщения шифруются как одно сообщение.
Терминология
Ключ авторизации
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 таков:
Где x = 0 для сообщений передаваемых от клиента к серверу и x = 8 для сообщений от сервера клиенту.
1024 бита нижнего порядка auth_key не включены в вычисление. Они могут (вместе с оставшимися битами или отдельно) использоваться на девайсе клиента для шифрования локальной копии данных, полученных от сервера. 512 бит нижнего порядка auth_key не хранятся на сервере; следовательно, если девайс клиента использует их, чтобы зашифровать локальные данные, и если юзер теряет ключ или пароль, расшифровка локальных данных невозможна (даже если могут быть получены данные с сервера).
Когда AES используется для шифровки блока данных длиной, не делимой по 16 байт, данные подбиваются рандомными байтами до минимальной длины, делимой по 16 байт, непосредственно перед тем как будут зашифрованы.
Важные тесты
Когда зашифрованное сообщение получено, должно быть проверено, что msg_key фактически равен 128 битам нижнего порядка хэша SHA1 от предварительно зашифрованной порции, и что msg_id имеет чётный результат для сообщений от клиента к серверу, и нечётный — для сообщений от сервера к клиенту.
Примечание переводчика: имеется в виду бит чётности. Вычисляется сложением по модулю 2, результат 0 считается чётным, результат 1 — нечётным.
Дополнительно, идентификаторы ( msg_id ) последних N сообщений, полученных от другой стороны, должны быть сохранены, и если сообщение приходит с msg_id меньшим или равным любому из сохранённых значений, сообщение будет проигнорировано. В противном случае, новый msg_id сообщения добавляется к комплекту, и, если число сохранённых значений msg_id больше чем N, самое старое (т. е. самое нижнее) забывается.
Дополнительно, значения msg_id , относящиеся ко времени более 30 секунд в будущем и более 300 секунд в прошлом, игнорируются. Это особенно важно для сервера. Для клиента это также будет полезным (для защиты от атаки повторного воспроизведения), но только если он его настройки времени точны (например, если его время было синхронизировано с временем сервера).
Определённые сервисные сообщения «от клиента к серверу», содержащие данные, отправленные клиентом серверу (например, msg_id последнего запроса клиента) могут, тем не менее, быть обработаны на/в клиенте даже если время «неправильное». Это особенно верно для сообщений, которые меняют сервер-salt и уведомлений о неправильных настройках времени у клиента. См. мобильный протокол: сервисные сообщения.
Сохранение ключа авторизации на клиенте
Юзерам, заботящимся о безопасности, может быть предложено защитить паролем ключ авторизации — примерно таким же способом как в ssh. Это достигается добавлением SHA1 ключа впереди ключа, после чего вся строка шифруется с использованием AES в режиме CBC и ключа, равного юзерскому (текстовому) паролю. Когда юзер вводит пароль, сохранённый защищённый пароль расшифровывается и проверяется сравнением с SHA1. С точки зрения юзера, это практически то же самое, что и использования пароля вебсайта или приложения.
Незашифрованные сообщения
Специальные только-текстовые сообщения могут быть использованы для создания ключа авторизации, также как для выполнения синхронизации времени. Они начинаются с auth_key_id = 0 (64 бита), что означает что здесь нет auth_key . За этим следует непосредственно тело сообщения в сериализованном формате без внутреннего и внешнего заголовка. Идентификатор сообщения (64 бита) и длина тела в байтах (32 байта) добавляются до тела сообщения.
Только очень ограниченное количество сообщений определённых типов могут быть переданы как только-текстовые.
Как получить id сообщения, отправленного ботом телеграмм?
Отправка файла телеграмм ботом
Здравствуйте, можете подсказать, как сделать отправку телеграмм ботом архива?
Кодировка сообщения, отправленного с сайта
доброго всем времени суток. есть форма обратной связи с прикреплением файла или картинки. брал из.
Некорректное отображение сообщения, отправленного на e-mail
Отсылаю себе сообщение на мэйл (текст сообщения «привет»), за место этого выдается сообщение.
Чтение сообщения Telegram-ботом
Привет. Пишу бота для ТГ, возникли трудности с чтением ботом сообщений из конкретного чата/канала.
Основной функционал мессенджера не позволяет узнавать идентификатор чата или свой, разработчиками не предусмотрена эта опция.
А если мне надо после отправки сообщения методом sendmessage при нажатии на кнопку изменить текст сообщения методом editmessagetext, тоже не получится?
Добавлено через 31 минуту
Сам разобрался: просто присвоил переменной метод bot.send_message, после аттрибуту в методе editmessagetext message_id присвоил переменная.message_id. Тему можно закрывать
Сразу же узнать "id" толькочто отправленного в базу сообщения!
Доброго времени суток, ситуация такая, отправляю в базу сообщение, мне нужно чтобы сразу после.
Получить данные от бота в телеграмм
Всем привет, пытаюсь получить данные от бота телеграмм Для начала зарегистрировал бота тут.
Не могу получить ответ от телеграмм бота
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters updater =.
Как вычислить айпи адрес письма, отправленного с gmail
Добрый день! Кругом и всюду эти любвеобильные красивые овдовевшие миллиардеры из Нигерии и.
Узнать message_id в Telegram API
Бот отправляет сообщение через bot.send_message() и потом для его изменения нужен chat_id и message_id. С chat_id проблем нет, но не могу понять где и как взять message_id отправленного ботом сообщения
Всё ещё ищете ответ? Посмотрите другие вопросы с метками python telegram-bot или задайте свой вопрос.
Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2022.8.30.42948
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Get message_id of the message that is being sent #699
Hello what i am trying to do is sending a message to two users and then edit both messages when they press the inline keyboard button, i already managed to edit the messsage of the user that pressed the button but it dosen’t edit the other message sent to the second user, i imagine that is becuase the two messages dont share the same message_id so i need to capture both id’s so i can use that variable on the edit_messge parameters
The text was updated successfully, but these errors were encountered:
diegoatsv commented Feb 13, 2019
First those are the two messages i send and the edit message works only on the user that press the button i need it to edit both messages when only one user press the button
alexandercerutti commented Feb 13, 2019 •
Look at this library API: where the methods return a «Promise», you can use a Javascript Promise. A promise is a way to execute things after an async operation has been executed.
You can use Promise.all() and pass it an array of Promises (like the two .sendMessage ) and get in its .then() callback as a value, an array of the contents returned by the promises.
sidelux commented Feb 15, 2019 •
Well, you should save both message_ids. When user click the inline button only the id of that message is sent.
So:
diegoatsv commented Feb 15, 2019 •
Well, you should save both message_ids. When user click the inline button only the id of that message is sent.
So:
Well my problem is how to store that message_id or both id’s in case the second user is the one that press the button, i already used the promise to see the info of both messages and understand how de message_id is created but id dont know how to store the data in a variable to be used when some one press the button
sidelux commented Feb 15, 2019
Just use a file or a database, or a global array like:
But you lost it when you restart your bot, i suggest to use a permanent resource.
diegoatsv commented Feb 15, 2019
Well ill be constantly sending the keyboards so the variables should rewrite themselves so it doesnt has to be an permanent data, so i just need to store both variables to be used in the moment, but to be honest i have no idea of how to do it so if you could give me an example i would be grateful.
sidelux commented Feb 15, 2019 •
Maybe something like this:
Is not tested but it should working as concept.
diegoatsv commented Feb 15, 2019
Thanks i made some modificactions to the code that @sidelux post because that was giving me a polling error when i pressed the keyboard button but now it works, but still thankyou so much for your help, i understand that the id’s will be lost the moment that some one send another keyboard but it’s ok and thanks to you @alexandercerutti for the idea of using promises