php - crear - telegram bot api python
¿Cómo implementar la autorización usando una API de Telegram? (4)
Como seguimiento de mi publicación original, una vez que haya terminado con los pasos de auth_key, lo siguiente será útil para ponerse al día rápidamente sobre cómo funciona el resto del telegrama.
1) Descarga y estudia el código fuente de Webogram , básicamente es JavaScript.
2) ejecute una copia local de Webogram modificada con console.logs para mostrarle paso a paso las interacciones que tienen lugar entre "un cliente de telegrama activo" y los servidores de telegramas. Esto le dará un flujo de trabajo sobre cómo funcionan realmente Telegram Clients y Telegram.
3) Use el lenguaje de desarrollo con el que se sienta más cómodo para construir su propia implementación de un analizador de protocolos para convertir flujos binarios en tipos de TL y viceversa.
De hecho, es bastante divertido codificar este paso. Acabo de construir un analizador de protocolos simple en Elixir
4) Aquí hay un registro de muestra de una copia modificada de Webogram.
Muestra los pasos a seguir después de generar con éxito su Auth_key
Incluso puede ver dónde tiene que generar una nueva Auth_key en vuelo, ya que cambia la validada al DataCenter adecuado, recreando su sesión, new server_salts, etc. (no se muestra)
Saludos.
ID time info log
121 12:26:35.318 new Auth Auth successfull! dc= 2 mtproto.js:479:15
127 12:26:35.325 CALL =>> API call help.getNearestDc Object { } Object { dcID: 2, createNetworker: true } mtproto.js:749:4
128 12:26:35.327 enc-START [invokeWithLayer] 45 mtproto.js:753:7
168 12:26:35.551 SEND POST XHR http://149.154.167.51/apiw1 [HTTP/1.1 200 OK 708ms]
189 12:26:36.522 msg-r <<=m [msg_container] Object { _: "msg_container", messages: Array[2] } mtproto.js:1452:5
190 12:26:36.523 msg-r <<=m [message] Object { _: "message", msg_id: "6242200678614200321", seqno: 1, bytes: 28, body: Object } mtproto.js:1452:5
191 12:26:36.525 msg-r <<=m [new_session_created] Object { _: "new_session_created", first_msg_id: "6242200671500883244", unique_id: "645797764649391412", server_salt: "17212767594123551779" } mtproto.js:1452:5
192 12:26:36.526 msg-r <<=m [message] Object { _: "message", msg_id: "6242200678630513665", seqno: 3, bytes: 28, body: Object } mtproto.js:1452:5
193 12:26:36.528 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200671500883244", result: Object } mtproto.js:1452:5
257 12:26:39.239 new Auth Auth successfull! dc= 4 mtproto.js:479:15
270 12:26:59.606 CALL =>> API call auth.sendCode Object { phone_number: "2348022002298", sms_type: 5, api_id: 38665, api_hash: "880c7847a517fc455d7d54731e90ad4e", lang_code: "en-US" } Object { dcID: 2, createNetworker: true } mtproto.js:749:4
321 12:27:00.048 SEND POST XHR http://149.154.167.51/apiw1 [HTTP/1.1 200 OK 422ms]
328 12:27:00.981 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200779464550396", result: Object } mtproto.js:1452:5
331 12:27:00.986 CALL =>> API call auth.sendCode Object { phone_number: "2348022002298", sms_type: 5, api_id: 38665, api_hash: "880c7847a517fc455d7d54731e90ad4e", lang_code: "en-US" } Object { dcID: "4", createNetworker: true, resultType: "auth.SentCode", messageID: "6242200779464550396" } mtproto.js:749:4
332 12:27:00.987 enc-START [invokeWithLayer] 45 mtproto.js:753:7
377 12:27:01.288 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 321ms]
398 12:27:02.170 msg-r <<=m [msg_container] Object { _: "msg_container", messages: Array[2] } mtproto.js:1452:5
399 12:27:02.171 msg-r <<=m [message] Object { _: "message", msg_id: "6242200787684582401", seqno: 1, bytes: 28, body: Object } mtproto.js:1452:5
400 12:27:02.172 msg-r <<=m [new_session_created] Object { _: "new_session_created", first_msg_id: "6242200784556418516", unique_id: "13396961033572361155", server_salt: "7076519506215495914" } mtproto.js:1452:5
401 12:27:02.173 msg-r <<=m [message] Object { _: "message", msg_id: "6242200787775901697", seqno: 3, bytes: 48, body: Object } mtproto.js:1452:5
402 12:27:02.174 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200784556418516", result: Object } mtproto.js:1452:5
407 12:27:02.344 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 25154ms]
414 12:27:03.068 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200779464550396" } mtproto.js:1452:5
420 12:27:15.639 CALL =>> API call auth.sendSms Object { phone_number: "2348022002298", phone_code_hash: "696b5befd8e809de81" } Object { dcID: "4", createNetworker: true, resultType: "auth.SentCode", messageID: "6242200784556418516" } mtproto.js:749:4
468 12:27:15.924 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 457ms]
475 12:27:17.154 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200848242727644", result: true } mtproto.js:1452:5
482 12:27:27.511 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200848242727644" } mtproto.js:1452:5
505 12:27:31.003 SEND POST XHR http://149.154.167.51/apiw1 [HTTP/1.1 200 OK 25161ms]
511 12:27:40.133 CALL =>> API call auth.signIn Object { phone_number: "2348022002298", phone_code_hash: "696b5befd8e809de81", phone_code: "26914" } Object { dcID: "4", createNetworker: true, resultType: "Bool", messageID: "6242200848242727644" } mtproto.js:749:4
560 12:27:40.454 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 756ms]
567 12:27:41.223 msg-r <<=m [msg_container] Object { _: "msg_container", messages: Array[2] } mtproto.js:1452:5
568 12:27:41.224 msg-r <<=m [message] Object { _: "message", msg_id: "6242200956100910081", seqno: 7, bytes: 80, body: Object } mtproto.js:1452:5
569 12:27:41.225 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200954555850604", result: Object } mtproto.js:1452:5
570 12:27:41.226 msg-r <<=m [message] Object { _: "message", msg_id: "6242200956751929345", seqno: 9, bytes: 88, body: Object } mtproto.js:1452:5
571 12:27:41.227 msg-r <<=m [updates] Object { _: "updates", updates: Array[1], users: Array[0], chats: Array[0], date: 1453375666, seq: 2 } mtproto.js:1452:5
579 12:27:41.758 CALL =>> API call updates.getState Object { } Object { noErrorBox: true } mtproto.js:749:4
586 12:27:41.842 CALL =>> API call account.updateStatus Object { offline: false } Object { noErrorBox: true } mtproto.js:749:4
594 12:27:41.850 CALL =>> API call messages.getDialogs Object { offset_date: 0, offset_id: 0, offset_peer: Object, limit: 20 } Object { timeout: 300 } mtproto.js:749:4
655 12:27:42.965 CALL =>> API call messages.getAllStickers Object { hash: "" } Object { } mtproto.js:749:4
696 12:27:43.920 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 908ms]
712 12:27:44.613 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 303ms]
727 12:27:46.488 msg-r <<=m [msg_container] Object { _: "msg_container", messages: Array[3] } mtproto.js:1452:5
728 12:27:46.489 msg-r <<=m [message] Object { _: "message", msg_id: "6242200970862778369", seqno: 11, bytes: 36, body: Object } mtproto.js:1452:5
729 12:27:46.489 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200960159395644", result: Object } mtproto.js:1452:5
730 12:27:46.490 msg-r <<=m [message] Object { _: "message", msg_id: "6242200970891641857", seqno: 13, bytes: 776, body: Object } mtproto.js:1452:5
731 12:27:46.492 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200960356118244", result: Object } mtproto.js:1452:5
732 12:27:46.494 msg-r <<=m [message] Object { _: "message", msg_id: "6242200970897958913", seqno: 15, bytes: 16, body: Object } mtproto.js:1452:5
733 12:27:46.495 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200960337591900", result: true } mtproto.js:1452:5
740 12:27:46.567 msg-r <<=m [msg_container] Object { _: "msg_container", messages: Array[4] } mtproto.js:1452:5
741 12:27:46.568 msg-r <<=m [message] Object { _: "message", msg_id: "6242200970862778369", seqno: 11, bytes: 36, body: Object } mtproto.js:1452:5
742 12:27:46.569 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200960159395644" } mtproto.js:1452:5
743 12:27:46.569 msg-r <<=m [message] Object { _: "message", msg_id: "6242200970891641857", seqno: 13, bytes: 776, body: Object } mtproto.js:1452:5
744 12:27:46.570 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200960356118244" } mtproto.js:1452:5
745 12:27:46.571 msg-r <<=m [message] Object { _: "message", msg_id: "6242200970897958913", seqno: 15, bytes: 16, body: Object } mtproto.js:1452:5
746 12:27:46.572 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200960337591900" } mtproto.js:1452:5
747 12:27:46.573 msg-r <<=m [message] Object { _: "message", msg_id: "6242200973791209473", seqno: 17, bytes: 76, body: Object } mtproto.js:1452:5
748 12:27:46.574 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200964892679524", result: Object } mtproto.js:1452:5
754 12:27:46.584 CALL =>> API call messages.getStickerSet Object { stickerset: Object } Object { } mtproto.js:749:4
811 12:27:47.346 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 539ms]
818 12:27:48.175 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242200981275507620", result: Object } mtproto.js:1452:5
857 12:27:49.351 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 25141ms]
864 12:27:57.219 msg-r <<=m [msgs_ack] Object { _: "msgs_ack", msg_ids: Array[0] } mtproto.js:1452:5
870 12:28:04.673 CALL =>> API call messages.readHistory Object { peer: Object, max_id: 0 } Object { } mtproto.js:749:4
908 12:28:04.860 CALL =>> API call messages.getHistory Object { peer: Object, offset_id: 16, add_offset: 0, limit: 20 } Object { timeout: 300, noErrorBox: true } mtproto.js:749:4
922 12:28:05.713 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 367ms]
929 12:28:06.096 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242201058769372356", result: Object } mtproto.js:1452:5
936 12:28:15.702 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242201058769372356" } mtproto.js:1452:5
977 12:28:16.122 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 25170ms]
983 12:28:26.637 CALL =>> API call account.updateStatus Object { offline: true } Object { noErrorBox: true } mtproto.js:749:4
1016 12:28:26.660 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 302ms]
1023 12:28:27.062 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242201153183272948", result: true } mtproto.js:1452:5
1030 12:28:41.985 msg-r <<=m [rpc_result] Object { _: "rpc_result", req_msg_id: "6242201153183272948" } mtproto.js:1452:5
1071 12:28:42.421 SEND POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 25165ms]
Quiero implementar múltiples autorizaciones usando PHP para interactuar con la API REST de Telegram.
¿Qué tarea estoy tratando de resolver? Bueno, es simple: varias docenas de usuarios (todos ellos tienen un carma como este (+10, -2, +1000, etc.) con una taxonomía grupal relevante: webmasters y clientes) tienen un perfil de usuario en mi sitio web. Después de alcanzar una cierta cantidad de carma y dado que están autorizados en su perfil, se unen a chats privados basados en Telegram generados automáticamente para ellos.
Después de algunas investigaciones, descubrí que es muy complicado porque:
- Nunca he tenido una experiencia de implementación API para redes sociales ligadas al hardware.
Eché un vistazo a https://core.telegram.org/api/auth , pero es completamente obvio cómo implementar estas funciones (por ejemplo, auth.sendCode), usando PHP o cualquier otro idioma. Si estos comandos se deben enviar como JSON al servidor, entonces no se parece a JSON:
auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;
¿Qué es? ¿En qué idioma está escrito?
UPD: está escrito en TL (Type Language): https://core.telegram.org/mtproto/TL
Exploré el código fuente de varios clientes (Webogram, Telegram-cli (tg), tdesktop) y encontré varias implementaciones de https://core.telegram.org/mtproto
Desafortunadamente, ninguno de ellos admite múltiples autorizaciones de su parte, y después de un poco de investigación, no tengo idea de dónde profundizar para obtener más información.
Además, estas implementaciones se ven voluminosas y compuestas (por ejemplo, https://github.com/vysheng/tg ):
Ahí veo un montón de servidores (./tg/tgl/tgl.h):
#define TG_SERVER_1 "149.154.175.50"
#define TG_SERVER_2 "149.154.167.51"
#define TG_SERVER_3 "149.154.175.100"
#define TG_SERVER_4 "149.154.167.91"
#define TG_SERVER_5 "149.154.171.5"
Encontré varias funciones posiblemente apropiadas (./tg/tgl/queries.c):
void empty_auth_file (void) {
if (TLS->test_mode) {
bl_do_dc_option (TLS, 1, "", 0, TG_SERVER_TEST_1, strlen (TG_SERVER_TEST_1), 443);
bl_do_dc_option (TLS, 2, "", 0, TG_SERVER_TEST_2, strlen (TG_SERVER_TEST_2), 443);
bl_do_dc_option (TLS, 3, "", 0, TG_SERVER_TEST_3, strlen (TG_SERVER_TEST_3), 443);
bl_do_set_working_dc (TLS, TG_SERVER_TEST_DEFAULT);
} else {
bl_do_dc_option (TLS, 1, "", 0, TG_SERVER_1, strlen (TG_SERVER_1), 443);
bl_do_dc_option (TLS, 2, "", 0, TG_SERVER_2, strlen (TG_SERVER_2), 443);
bl_do_dc_option (TLS, 3, "", 0, TG_SERVER_3, strlen (TG_SERVER_3), 443);
bl_do_dc_option (TLS, 4, "", 0, TG_SERVER_4, strlen (TG_SERVER_4), 443);
bl_do_dc_option (TLS, 5, "", 0, TG_SERVER_5, strlen (TG_SERVER_5), 443);
bl_do_set_working_dc (TLS, TG_SERVER_DEFAULT);
}
}
void bl_do_dc_option (struct tgl_state *TLS, int id, const char *name, int l1, const char *ip, int l2, int port) {
struct tgl_dc *DC = TLS->DC_list[id];
if (DC && !strncmp (ip, DC->ip, l2)) { return; }
clear_packet ();
out_int (CODE_binlog_dc_option);
out_int (id);
out_cstring (name, l1);
out_cstring (ip, l2);
out_int (port);
add_log_event (TLS, packet_buffer, 4 * (packet_ptr - packet_buffer));
}
etc.
¿Qué archivos debo transferir a PHP para la implementación de autenticación de usuario múltiple? ¿Podría ayudarme a saber por dónde empezar y cómo hacerlo más fácil de lo que es actualmente?
¡Gracias de antemano!
Escribí una implementación PHP de mtproto, y hasta ahora he logrado implementar serialización / deserialización TL, conexiones abreviadas / intermedias / completas tcp, conexiones http / https.
Implementé envolturas OOP para todos los métodos mtproto, un módulo de generación principal basado en Python / wolfram alpha / php, análisis HTML / Markdown con soporte para menciones, soporte de identificación de archivos bot API, manejo de actualizaciones con devoluciones de llamada o actualizaciones, bot API <-> Conversión de objeto MTProto, envoltorios de carga / descarga, envoltorios de inicio de sesión para bots / usuarios (2FA es compatible), manejo simple de errores, gestión interna de pares (puede proporcionar un id. De chat de API bot simple, un nombre de usuario o id. De igual en formato tg-cli enviar un mensaje o llamar a otros métodos de mtproto) y actualmente estoy trabajando en un buen contenedor Lua para permitir el uso de bots td-cli / tg-cli con MadelineProto.
También escribí una clase para generar documentación para todos los métodos / constructores / tipos de mtproto (disponible en https://daniil.it/MadelineProto/API_docs ). MadelineProto se puede serializar en un archivo para permitir el almacenamiento fácil de la sesión.
Si alguien está interesado o quiere contribuir, aquí está el enlace al repositorio de github: https://github.com/danog/MadelineProto
Hasta ahora he podido implementar la autorización del telegrama por completo, pero no en el idioma solicitado. PHP, utilicé vb.Net. Sin embargo, creo que la misma lógica debería aplicarse.
Crear una clave de autorización de Telegram
Telegram API no es caminar en el parque. Estudiar el código src existente podría ser bastante desalentador (en mi humilde opinión). Por lo tanto, mi enfoque fue estudiar la documentación de la API en línea e implementar la clave de autenticación de muestra que se describe en los enlaces a continuación.
https://core.telegram.org/mtproto/auth_key
https://core.telegram.org/mtproto/samples-auth_key
Lo que este enfoque le proporcionará es una mejor comprensión e introducción a las primitivas utilizadas en Telegram API, y posiblemente le ayude a comenzar a organizar su propio conjunto de funciones y rutinas para manejar las que necesitará para los siguientes pasos: implementar otras funciones de la API , ya que generar una AuthKey es solo el comienzo.
Paso 1
Toda la comunicación es a través de TCP: una vez que haya obtenido un api_id único ( https://core.telegram.org/api/obtaining_api_id#obtaining-api-id ) encontrará la siguiente IP anunciada para su uso en las pruebas: 149.154.167.40: 433 El api_id no es requerido en este punto para generar una AuthKey
Configure su método preferido de procesamiento de TCP de envío / recepción
lo que tengo es un SendData privado que simplemente envía un byte a un socket en vivo conectado a la dirección IP dada arriba
Private Sub SendData(b() As Byte, Optional read As Boolean = False)
If Not IsConnected() Then
Log("Connection Closed!", ConsoleColor.DarkRed)
RaiseEvent Disconneted()
Exit Sub
End If
b = TCPPack(b)
Dim arg = New SocketAsyncEventArgs With {.RemoteEndPoint = ep}
AddHandler arg.Completed, AddressOf IO_Handler
arg.SetBuffer(b, 0, b.Length)
Try
If Not soc.SendAsync(arg) Then
IO_Handler(soc, arg)
End If
If read Then
ReadData()
End If
Catch ex As Exception
Log("SendData: " & ex.ToString, ConsoleColor.Red)
End Try
End Sub
Private Sub ReadData(Optional wait As Integer = 0)
If Not IsConnected() Then
Log("Connection Closed!", ConsoleColor.DarkRed)
RaiseEvent Disconneted()
Exit Sub
End If
Dim arg = New SocketAsyncEventArgs With {.RemoteEndPoint = ep}
AddHandler arg.Completed, AddressOf IO_Handler
Dim b(BUFFER_SIZE - 1) As Byte
arg.SetBuffer(b, 0, BUFFER_SIZE)
Try
If Not soc.ReceiveAsync(arg) Then
IO_Handler(soc, arg)
End If
Catch ex As Exception
Log("ReadMessages: " & ex.ToString, ConsoleColor.Red)
End Try
End Sub
Private Sub IO_Handler(sender As Object, e As SocketAsyncEventArgs)
Log($"{e.LastOperation}:{e.SocketError}:{e.BytesTransferred}", ConsoleColor.Cyan)
Select Case e.SocketError
Case SocketError.Success
Select Case e.LastOperation
Case SocketAsyncOperation.Connect ''A socket Connect operation.
Log("Connected to " & e.ConnectSocket.RemoteEndPoint.ToString, ConsoleColor.Green)
are.Set()
Case SocketAsyncOperation.Disconnect, SocketAsyncOperation.Connect
RaiseEvent Disconneted()
Case SocketAsyncOperation.Receive ''A socket Receive operation.
HandleData(e)
End Select
Case SocketError.ConnectionAborted
RaiseEvent Disconneted()
End Select
End Sub
Private Sub HandleData(e As SocketAsyncEventArgs)
If e.BytesTransferred = 0 Then --no pending data
Log("The remote end has closed the connection.")
Exit Sub
End If
Dim len As Integer = e.Buffer(0)
Dim start = 1
If len = &H7F Then
len = e.Buffer(1)
len += e.Buffer(2) << 8
len += e.Buffer(3) << 16
start = 4
End If
len = 4 * len
Dim data(len - 1) As Byte
Array.Copy(e.Buffer, start, data, 0, len)
ProcessResponse(data)
ReadData()
End Sub
Finalmente, para este paso, necesitamos un método TcpPack () que nos ayude a rellenar nuestros datos en el formato que Telegram espera: consulte el siguiente código con los comentarios
Private Function TCPPack(b As Byte()) As Byte()
Dim a = New List(Of Byte)
Dim len = CByte(b.Length / 4)
If efSent = False Then --TCP abridged version
efSent = True
a.Add(&HEF)
End If
If len >= &H7F Then
a.Add(&H7F)
a.AddRange(BitConverter.GetBytes(len))
Else
a.Add(len)
End If
a.AddRange(b) --only data, no sequence number, no CRC32
Return a.ToArray
End Function
PASO 2
Con la configuración básica de rutinas de envío / recepción TCP, podemos comenzar a preparar paquetes de datos para enviar a telegramas y tener sub rutinas para manejar las respuestas específicas recibidas - ProcessResponse (datos)
Lo que necesitamos entender a continuación es el hecho de que Telegram maneja 2 amplias categorías de mensajes:
Sin encriptar - https://core.telegram.org/mtproto/description#unencrypted-message
Estos son mensajes de texto sin formato con su auth_key_id =0
genera un AuthKey utiliza este tipo de mensaje a lo largo de
Encriptado - https://core.telegram.org/mtproto/description#encrypted-message-encrypted-data
Toda comunicación adicional con los servidores de Telegram será a través de mensajes cifrados
Elijo tener dos clases para encapsular ambos tipos de mensajes. Puedo tener dos métodos Send (m) que manejen cada tipo
Private Sub Send(m As UnencryptedMessage)
Log(m.ToString, ConsoleColor.DarkYellow, logTime:=False)
SendData(m.data, True)
End Sub
Private Sub Send(m As EncryptedMessage)
Log(m.ToString, ConsoleColor.DarkYellow, logTime:=False)
SendData(m.data, True)
End Sub
Por ahora solo se requiere UnencryptedMessage
Public Class UnencryptedMessage
Public Property auth_key_id As Int64
Public Property message_id As Int64
Public Property data_length As Int32
Public Property message_data As Byte()
Public Property message_type As String
Public Property data As Byte() = {}
Sub New(auth_key As Int64, message_id As Int64, data As Byte())
_auth_key_id = auth_key
_message_id = message_id
_data_length = data.Length
_message_data = data
message_type = B2Hr(data, 0, 4)
Dim a = New List(Of Byte)
a.AddRange(BitConverter.GetBytes(auth_key_id)) --{0, 0, 0, 0, 0, 0, 0, 0}
a.AddRange(BitConverter.GetBytes(message_id))
a.AddRange(BitConverter.GetBytes(data_length))
a.AddRange(message_data)
Me.data = a.ToArray
End Sub
Sub New(b As Byte())
data = b
Dim skip = 0
_auth_key_id = BitConverter.ToInt64(b, skip) : skip += 8
_message_id = BitConverter.ToInt64(b, skip) : skip += 8
_data_length = BitConverter.ToInt32(b, skip) : skip += 4
ReDim _message_data(_data_length - 1)
Array.Copy(b, skip, _message_data, 0, b.Length - skip)
message_type = B2Hr(_message_data, 0, 4)
End Sub
Public Overrides Function ToString() As String
Return $"
raw_data: {B2H(data)}
auth_key_id: {i2H(auth_key_id)} {auth_key_id}
message_id: {i2H(message_id)} {message_id}
data_length: {i2H(data_length)} {data_length}
message_data: {B2H(message_data)}
message_type: {message_type}
"
End Function
End Class
PASO 3
Ahora seguimos la serie de pasos descritos en https://core.telegram.org/mtproto/auth_key
1) El cliente envía una consulta al servidor
req_pq # 60469778 nonce: int128 = ResPQ El valor de nonce se selecciona aleatoriamente por el cliente (número aleatorio) e identifica al cliente dentro de esta comunicación. Siguiendo este paso, es conocido por todos.
2) El servidor envía la respuesta del formulario
resPQ # 05162463 nonce: int128 server_nonce: int128 pq: string server_public_key_fingerprints: Vector long = ResPQ
Mi enfoque para esto es muy simple:
Sub RequestPQAuthorization()
Send(MTProto.req_pq)
End Sub
En una clase llamada MTProto, implemento un conjunto de funciones compartidas según lo requiera cada paso del intercambio. Cada método simplemente está construyendo una estructura de datos cifrados que se enviará como se indica arriba cuando sea necesario.
Comenzamos con: req_pq
Shared Function req_pq(Optional nonce As Byte() = Nothing) As UnencryptedMessage
--req_pq#60469778
--nonce:int128
If nonce Is Nothing Then
ReDim nonce(15)
RND.NextBytes(nonce)
End If
Dim d = New List(Of Byte)
d.AddRange({120, 151, 70, 96}) --60469778
d.AddRange(nonce)
Return New UnencryptedMessage(0, CreateMessageId, d.ToArray)
End Function
Private Shared Function CreateMessageId() As Int64
Return CLng((Date.UtcNow.Ticks - ZERO_TICK) * 429.4967296)
End Function
Public Const ZERO_TICK = 621355968000000000 -- i.e. 1970-01-01T00:00:00Z (January 1, 1970, at 12:00 AM UTC)
Ahora nuestro método de respuesta al proceso del Paso 1
Private Sub ProcessResponse(data As Byte())
Try
Dim r = New UnencryptedMessage(data)
Log(r.ToString, ConsoleColor.Yellow, logTime:=False)
Select Case r.message_type
Case resPQ.Classid
RequestDHKeyExchange(New resPQ(r.message_data))
Case server_DH_params_ok.Classid
RequestSetDH_params(New server_DH_params_ok(r.message_data), new_nonce)
Case server_DH_params_fail.Classid
Log(New server_DH_params_fail(r.message_data).ToString, ConsoleColor.DarkMagenta)
Case dh_gen_ok.Classid
Log(New dh_gen_ok(r.message_data).ToString, ConsoleColor.Green)
Case dh_gen_retry.Classid
Log(New dh_gen_retry(r.message_data).ToString, ConsoleColor.DarkMagenta)
Case dh_gen_fail.Classid
Log(New dh_gen_fail(r.message_data).ToString, ConsoleColor.DarkMagenta)
Case Else
Log($"Unhandled type: {r.message_type}", ConsoleColor.Magenta)
End Select
Catch ex As Exception
Log($"Error: {ex.ToString}", ConsoleColor.Red)
Log(B2H(data), ConsoleColor.DarkRed, logTime:=False)
End Try
End Sub
Excelente hasta ahora, cada respuesta recibida tiene un código de tipo de mensaje.
podemos encender eso y determinar cómo se maneja cada uno. Necesitamos procesar resPQ ahora mismo.
Lo que he hecho es crear un conjunto de clases que maneje un tipo de respuesta específico
'''''' <summary>
'''''' resPQ#05162463
'''''' nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector long = ResPQ
'''''' </summary>
Public NotInheritable Class resPQ : Inherits TLObject
Public Shared Shadows ReadOnly Property Classid As String = "05162463"
Public Property nonce As Byte()
Public Property server_nonce As Byte()
Public Property pq As Byte()
Public Property fingerprints As List(Of UInt64)
Public Property count As Int32
Sub New(data As Byte())
Dim skip = 4
nonce = Slice(data, skip, 16) : skip += 16
server_nonce = Slice(data, skip, 16) : skip += 16
skip += 1 ''length of pq:string
pq = Slice(data, skip, 8) : skip += 8
skip += 3 ''padding to complete the 4-bytes
skip += 4 ''%(Vector long) 1cb5c415
count = i32r(data, skip) : skip += 4
fingerprints = New List(Of UInt64)
For i = 0 To count - 1
fingerprints.Add(u64r(data, skip))
Next
End Sub
Public Overrides Function ToString() As String
Return $"
classid: {NameOf(resPQ)}#{Classid}
nonce: {B2H(nonce)}
server_nonce: {B2H(server_nonce)}
pq: {B2H(pq)} {u64(pq)}
count: {i2H(count)} {count}
fingerprints: {i2H(fingerprints(0))} {fingerprints(0)}
"
End Function
End Class
Cada uno se basa en este simple objeto
Public MustInherit Class TLObject
Public Shared Property ClassId As String
Public MustOverride Overrides Function ToString() As String
End Class
Sobre la base de esto, abordamos los pasos 3 y 4
Prueba de trabajo 3) El cliente descompone pq en factores primos tales que p <q.
Esto inicia una ronda de intercambios de claves Diffie-Hellman.
Presentar prueba de trabajo; Autenticación del servidor 4) El cliente envía la consulta al servidor
req_DH_params # d712e4be nonce: int128 server_nonce: int128 p: cadena q: cadena public_key_fingerprint: long encrypted_data: string = Server_DH_Params
Esto se inicia aquí RequestDHKeyExchange(New resPQ(r.message_data))
en mi rutina ProcessResponse
anterior
Sub RequestDHKeyExchange(r As resPQ)
Log(r.ToString, ConsoleColor.Gray, logTime:=False)
''decompose prime cofactors
Dim pp = New PrimeProduct(r.pq)
Log(pp.ToString, ConsoleColor.Gray, logTime:=False)
''encrypted_data Generation
Dim pq = New P_Q_inner_data(r.pq, pp.p, pp.q, r.nonce, r.server_nonce)
new_nonce = pq.new_nonce
''The serialization Of P_Q_inner_data produces some String data. This Is followed by encrypted_data
''data_with_hash := SHA1(data) + data + (any random bytes); such that the length equal 255
Dim data_with_hash = New List(Of Byte)
''SHA1(data) = xxx- 40 =20 bytes
Using sha1 = New SHA1Managed
Dim b = pq.ToBytes
data_with_hash.AddRange(sha1.ComputeHash(b))
data_with_hash.AddRange(b)
End Using
If data_with_hash.Count < 255 Then
Dim pad(255 - data_with_hash.Count - 1) As Byte
RND.NextBytes(pad)
data_with_hash.AddRange(pad)
End If
''RSA(data_with_hash, server_public_key) = xxx - 512 = 256 bytes
Dim key = i2H(r.fingerprints(0)) ''c3b42b026ce86b21
Dim zb = Crypto.rsaEncrypt(data_with_hash.ToArray, key)
Send(MTProto.req_DH_params(r.nonce, r.server_nonce, pp.p, pp.q, r.fingerprints(0), zb))
End Sub
Puede usar su propia implementación de Prime-Decomposition para reemplazar esta línea Dim pp = New PrimeProduct(r.pq)
Aquí hay un ejemplo de cómo aprendí hacerlo usando PollardBrent (Pollard Rho Brent Integer Factorization) https://.com/a/31978350/44080
De acuerdo, si puedes seguir hasta este punto, tienes una idea general de cómo estoy descomponiendo la implementación de AuthKey paso a paso.
Debería poder ejecutar los pasos restantes 5-9. Es mucho para mí escribir ...
Si esta respuesta hasta ahora es de alguna ayuda para alguien, entonces tomaré tiempo para organizar y publicar la parte restante.
Creo que las rutinas y el conocimiento que acumule a lo largo del camino le brindarán las herramientas que necesita para comprender e implementar su propio código independiente de la API de Telegram desde cero.
Vaciado de interacción completado
03:33:26.591 Connect:Success:0
03:33:26.593 Connected to 149.154.167.40:443
03:33:26.598
raw_data: 000000000000000000DC799836FE075614000000789746604479257F6C01C039A3DEAD031BC2D6A4
auth_key_id: 0000000000000000 0
message_id: 5607FE369879DC00 6199202922538589184
data_length: 00000014 20
message_data: 789746604479257F6C01C039A3DEAD031BC2D6A4
message_type: 60469778
03:33:26.600 Send:Success:42
03:33:26.735 Receive:Success:85
03:33:26.737
raw_data: 0000000000000000015CF64539FE075640000000632416054479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D0818DDCAF407B7CDCD00000015C4B51C01000000216BE86C022BB4C3
auth_key_id: 0000000000000000 0
message_id: 5607FE3945F65C01 6199202934039141377
data_length: 00000040 64
message_data: 632416054479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D0818DDCAF407B7CDCD00000015C4B51C01000000216BE86C022BB4C3
message_type: 05162463
03:33:26.743
classid: resPQ#05162463
nonce: 4479257F6C01C039A3DEAD031BC2D6A4
server_nonce: 4F9DB065B36308CF4D9965725DD7153D
pq: 18DDCAF407B7CDCD 1791811376213642701
count: 00000001 1
fingerprints: C3B42B026CE86B21 14101943622620965665
03:33:26.810
PQ: 18DDCAF407B7CDCD 1791811376213642701
P: 45F57B87 1173715847
Q: 5AFE490B 1526614283
03:33:26.930
raw_data: 000000000000000000403CEE36FE075640010000BEE412D74479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D0445F57B87000000045AFE490B000000216BE86C022BB4C3FE0001002DD190DDD93DFFC9EAF14DFAD3018D101E9E3EEC6C3FF4C7C1A067B32FB19AA2FDDFD087094947E793FA9F1A10A36A0B2916609811CFF1F345EE8FD9CDFFBCA4555E33A0446AB4A534500F621D112FCF59CAD4961BC87375F6835460B2E1B3B4088CE79843F7445DC5D87E0ACB0C4A979F68240C06358C4D2F95F86C0535CA643FBE8AF730E70BCBB54191D4F110E50D3244882722605657E808382445FA070A67AED1B2835238C05A00EBE960106838A284BC03D7A01453BA5355F06952F686263DD5B22B66524ED47F843340E9B7FC75BD58B6CC376C0B8B89E7292EDCC08D6CD0F1F9BF8418C2A58BC82B1928B051B3A0C20FA0AB22BA822EFABA6E141508
auth_key_id: 0000000000000000 0
message_id: 5607FE36EE3C4000 6199202923977392128
data_length: 00000140 320
message_data: BEE412D74479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D0445F57B87000000045AFE490B000000216BE86C022BB4C3FE0001002DD190DDD93DFFC9EAF14DFAD3018D101E9E3EEC6C3FF4C7C1A067B32FB19AA2FDDFD087094947E793FA9F1A10A36A0B2916609811CFF1F345EE8FD9CDFFBCA4555E33A0446AB4A534500F621D112FCF59CAD4961BC87375F6835460B2E1B3B4088CE79843F7445DC5D87E0ACB0C4A979F68240C06358C4D2F95F86C0535CA643FBE8AF730E70BCBB54191D4F110E50D3244882722605657E808382445FA070A67AED1B2835238C05A00EBE960106838A284BC03D7A01453BA5355F06952F686263DD5B22B66524ED47F843340E9B7FC75BD58B6CC376C0B8B89E7292EDCC08D6CD0F1F9BF8418C2A58BC82B1928B051B3A0C20FA0AB22BA822EFABA6E141508
message_type: D712E4BE
03:33:26.933 Send:Success:341
03:33:27.217 Receive:Success:656
03:33:27.217
raw_data: 0000000000000000011C9A9F39FE0756780200005C07E8D04479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153DFE500200752C7BDBB6A58D68B76D2E20DCECF611B2837CA34F3688B242192C633FBBC1EC9348880DA6E6AFF42B256D8476A2C432B60E93218F5B84982B0F9800E6EF918AEC4B729AB1A67C82EF2C4D281352D1BEAEB6B9026CAA0CA8FB03F9257E2CA034471EE25CF6E214BB770E233566A67155BE8FB8F9DA0A76964CFD19E9C97D3E57AAA26E7A6C16B12F2B2BFD4C437857032F0A7198567B9CD3A54BD06CE61A1EBACD70D464185719BC8E0381C99E80A5783D389BE73E97166A328CEDB3AA4D722D453EB4CA893299E41DDC81C798BC76CAF070BFF144F6800D8FE5B3B6BCC9A1138E7ADA6DAF3F581AAB0137A6D40E640E76F6539B1450EA30A55E3F56C2C0A8DCC6F9F4D4F185D25AF37B46B9D9B8ED5CA257DD32EDE02FF95C6174C9D4BA1E30035723C7E2DED9EB0794AAA1913073E4EA2D5649C5C491B252AF88FF1D71EFB5E9FFCA921F0F27F72723DD5014359D08101278DF3F9A9A10DDE54B93A386C6844A6D15AF142DA956A3999458D10BBDE4E947BE949199F088B91175EC9EEE3C95AC47C96D802B0DC91AA6DB5B8A03E0985412DD23CD33FD961175CD271E02BF8A05A537E8FE21CDB40EBAAC0C8D4718DA4499D5B5EF935B848F92C25E9CAE76021758EDD1AA202A0D0DC357348B0474069002EB8F5F2760F2C5BEE38C7CEA07737C28864F647F2406BD55ABD58EEED97A4C8E659143441B1F8CB8DEFE457B46B5E76541CAB63FA1CD3626F0A45DB8A37964BF2613A6C64E6E6E478D44A2AF19CAD6C2686FD55EC85CACD645E58C364CBBD09EF1C7FE7420A8EF277982B87CA18D16B97980B14D24747D9BC86563DA81DA
auth_key_id: 0000000000000000 0
message_id: 5607FE399F9A1C01 6199202935543045121
data_length: 00000278 632
message_data: 5C07E8D04479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153DFE500200752C7BDBB6A58D68B76D2E20DCECF611B2837CA34F3688B242192C633FBBC1EC9348880DA6E6AFF42B256D8476A2C432B60E93218F5B84982B0F9800E6EF918AEC4B729AB1A67C82EF2C4D281352D1BEAEB6B9026CAA0CA8FB03F9257E2CA034471EE25CF6E214BB770E233566A67155BE8FB8F9DA0A76964CFD19E9C97D3E57AAA26E7A6C16B12F2B2BFD4C437857032F0A7198567B9CD3A54BD06CE61A1EBACD70D464185719BC8E0381C99E80A5783D389BE73E97166A328CEDB3AA4D722D453EB4CA893299E41DDC81C798BC76CAF070BFF144F6800D8FE5B3B6BCC9A1138E7ADA6DAF3F581AAB0137A6D40E640E76F6539B1450EA30A55E3F56C2C0A8DCC6F9F4D4F185D25AF37B46B9D9B8ED5CA257DD32EDE02FF95C6174C9D4BA1E30035723C7E2DED9EB0794AAA1913073E4EA2D5649C5C491B252AF88FF1D71EFB5E9FFCA921F0F27F72723DD5014359D08101278DF3F9A9A10DDE54B93A386C6844A6D15AF142DA956A3999458D10BBDE4E947BE949199F088B91175EC9EEE3C95AC47C96D802B0DC91AA6DB5B8A03E0985412DD23CD33FD961175CD271E02BF8A05A537E8FE21CDB40EBAAC0C8D4718DA4499D5B5EF935B848F92C25E9CAE76021758EDD1AA202A0D0DC357348B0474069002EB8F5F2760F2C5BEE38C7CEA07737C28864F647F2406BD55ABD58EEED97A4C8E659143441B1F8CB8DEFE457B46B5E76541CAB63FA1CD3626F0A45DB8A37964BF2613A6C64E6E6E478D44A2AF19CAD6C2686FD55EC85CACD645E58C364CBBD09EF1C7FE7420A8EF277982B87CA18D16B97980B14D24747D9BC86563DA81DA
message_type: D0E8075C
03:33:27.240
classid: server_DH_params_ok#D0E8075C
nonce: 4479257F6C01C039A3DEAD031BC2D6A4
server_nonce: 4F9DB065B36308CF4D9965725DD7153D
enc_answer: 752C7BDBB6A58D68B76D2E20DCECF611B2837CA34F3688B242192C633FBBC1EC9348880DA6E6AFF42B256D8476A2C432B60E93218F5B84982B0F9800E6EF918AEC4B729AB1A67C82EF2C4D281352D1BEAEB6B9026CAA0CA8FB03F9257E2CA034471EE25CF6E214BB770E233566A67155BE8FB8F9DA0A76964CFD19E9C97D3E57AAA26E7A6C16B12F2B2BFD4C437857032F0A7198567B9CD3A54BD06CE61A1EBACD70D464185719BC8E0381C99E80A5783D389BE73E97166A328CEDB3AA4D722D453EB4CA893299E41DDC81C798BC76CAF070BFF144F6800D8FE5B3B6BCC9A1138E7ADA6DAF3F581AAB0137A6D40E640E76F6539B1450EA30A55E3F56C2C0A8DCC6F9F4D4F185D25AF37B46B9D9B8ED5CA257DD32EDE02FF95C6174C9D4BA1E30035723C7E2DED9EB0794AAA1913073E4EA2D5649C5C491B252AF88FF1D71EFB5E9FFCA921F0F27F72723DD5014359D08101278DF3F9A9A10DDE54B93A386C6844A6D15AF142DA956A3999458D10BBDE4E947BE949199F088B91175EC9EEE3C95AC47C96D802B0DC91AA6DB5B8A03E0985412DD23CD33FD961175CD271E02BF8A05A537E8FE21CDB40EBAAC0C8D4718DA4499D5B5EF935B848F92C25E9CAE76021758EDD1AA202A0D0DC357348B0474069002EB8F5F2760F2C5BEE38C7CEA07737C28864F647F2406BD55ABD58EEED97A4C8E659143441B1F8CB8DEFE457B46B5E76541CAB63FA1CD3626F0A45DB8A37964BF2613A6C64E6E6E478D44A2AF19CAD6C2686FD55EC85CACD645E58C364CBBD09EF1C7FE7420A8EF277982B87CA18D16B97980B14D24747D9BC86563DA81DA
tmp_aes_key: 297CB750FF0052B67515B3F11B45F11F15D106BC25ED0027570D5B9D83102BFA
tmp_aes_iv: CBDCF40A77B6A1C7CE74A1F8EC8E091A49FAD3B9A2499BFFFD084D537A53B36D
answer: BA0D89B54479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE000100C49E858CA0107FF9B51DC88236370866BE4A69DDC2193930769C11722D2884CE5017AF60712B6BAC17F79DBA8701A25AAA901FDCB483C56A246C1CA7705FAA87F0AFD68EAC8FC5EC88307298DAF7252DD6D8630BF819D65F9E4B5624B6A05149B35B8509A63C2F2D05417F38DD0A90727F5D12CC4D213B5974C732FB261F6AC01426F2B7269C17230442AA8C9AFCCD927463C4EC8465F841D969F0C47FC270D8EC23B1F5D861EB6A5602CF6F87A02A56A4094E06509503CACE935461086668AC32E8C69A90EB19C3232B20635DFADFC6E4EDC11FA34A3E2E2BBA28DDCEF422120077D3A171A6A5B65744113AF0D0A1FC566D31DBBDB43F5DE35A7CE5F0BB0ECD39FE0756646CF781176C3EAC
classid: Server_DH_inner_data#B5890DBA
nonce: 4479257F6C01C039A3DEAD031BC2D6A4
server_nonce: 4F9DB065B36308CF4D9965725DD7153D
g: 00000003 3
dh_prime: C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B
g_a: C49E858CA0107FF9B51DC88236370866BE4A69DDC2193930769C11722D2884CE5017AF60712B6BAC17F79DBA8701A25AAA901FDCB483C56A246C1CA7705FAA87F0AFD68EAC8FC5EC88307298DAF7252DD6D8630BF819D65F9E4B5624B6A05149B35B8509A63C2F2D05417F38DD0A90727F5D12CC4D213B5974C732FB261F6AC01426F2B7269C17230442AA8C9AFCCD927463C4EC8465F841D969F0C47FC270D8EC23B1F5D861EB6A5602CF6F87A02A56A4094E06509503CACE935461086668AC32E8C69A90EB19C3232B20635DFADFC6E4EDC11FA34A3E2E2BBA28DDCEF422120077D3A171A6A5B65744113AF0D0A1FC566D31DBBDB43F5DE35A7CE5F0BB0ECD
server_time: 5607FE39 1443364409
client_time: 5607FE37 1443364407
padding: 646CF781176C3EAC
DH_Prime is Safe? = True
classid: Client_DH_Inner_Data#6643B654
nonce: 4479257F6C01C039A3DEAD031BC2D6A4
server_nonce: 4F9DB065B36308CF4D9965725DD7153D
retry_id: 0000000000000000 0
g_b: 923A21384FE0318D569B2F2BEA667D1A999050A0A1B5AFDA39F2B890DEE45F9ED08E319C8243CD1496269CCF956DFA6C98633BDC2E26B1675C15D7904417EC2A74C687E682ED14182178BC0BD189F6E020131C87FD42A24798FCCD2416348EE0AAF534B652175BAC33E89C82874A8C3E8562815DDA213610167B10153EFC1BD1A0CFBACFEA22E3E8D80917F262D2C67BF1327A245CF7FE0E299F7517EE6A2F65568630A6191FEB0C1254F260A6554ED2BEE19E94AAB693E58DD032C26B9CAFEB0482F12DE2573B6E6D2816AC37ADDF3B99525FDBAF94690926320CC67ABF35D3EA6EC6CC7211BAF11FBDD6897959F6F1E3D4335B89B3024C1B3C0066246B5DCD
03:33:27.590 enc_data: 0A974C499344B093ADF321597858B1A6179E2A6C21F5FF9EB5DE687CDB57F8059509482FF9846FBE99D9411C13A645B26F73960424A13337D87DA879864FCA9D0883B643CF8EB594446038E0B6C4FD606D0CB77F1E00CCA6291DD65733F6A60217C7F366AD88972F107C381FD375F49DB57A2AB96988EC916629CD6F58B53F65DF4909AA773CCA43CE43671CA313528190213CF28A3B29BE26865BE22EB0C41E89CBD698C96CBC1B7B7F1586FBD61B422693859843F7D32083E3AB23D607FC4B874DB849F430F74483969ABA4603B483C94BCEB38F8EC90EEB58B338B325A8E37B57813CEC7E795B1B5517D732227856955C53BA18F52E55C6BCD8F1419D43D46DF2C2560B74BA7AA961BB4BDD09ABBC95E4F57AC4B8C89A67C7C5453A3EFB635D3977E0C3F0067C1F4D255F1F87E74A8E7E4272DFDEB9B85ABBEFA4953B2E0ECAA15C3C77773155C4013955BAB0D85F
03:33:27.810 auth_Key: 87A801A14AD6426E6AD56B638B315DF9F5B66F77333DC8C0FAADB77A1D51E71B68F5BB9B21DB275F2C4CA495E6440DDEACBDB199C52C327F7E2E9D78921E0D632CCA63DB6384FAF387E9D41717899EE5D54609C2F88573BBE8128FB5864CB62BC7F0ED250CBB57929AA5198FE568FC76FB846262A505B42D04BCB87C9EB24007CE9F9BDEB79391E7E9425F3A3D5028410E129C078EB8644EAB770F8705D8228CFAEAA4478A0D8E326971C7C2223074C4302C1F1DE5D08AC00CBEBEE41981B57A4248B517386DE68A51D01087F0E58D75A4C0FD2D031BC5BFC08651C4133494B572150EDD1C486153E8F51F99771DD57F55B3A5BBAE1874F25E69150C4E3C1397
03:33:27.813
raw_data: 0000000000000000009C48D037FE0756780100001F5F04F54479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153DFE5001000A974C499344B093ADF321597858B1A6179E2A6C21F5FF9EB5DE687CDB57F8059509482FF9846FBE99D9411C13A645B26F73960424A13337D87DA879864FCA9D0883B643CF8EB594446038E0B6C4FD606D0CB77F1E00CCA6291DD65733F6A60217C7F366AD88972F107C381FD375F49DB57A2AB96988EC916629CD6F58B53F65DF4909AA773CCA43CE43671CA313528190213CF28A3B29BE26865BE22EB0C41E89CBD698C96CBC1B7B7F1586FBD61B422693859843F7D32083E3AB23D607FC4B874DB849F430F74483969ABA4603B483C94BCEB38F8EC90EEB58B338B325A8E37B57813CEC7E795B1B5517D732227856955C53BA18F52E55C6BCD8F1419D43D46DF2C2560B74BA7AA961BB4BDD09ABBC95E4F57AC4B8C89A67C7C5453A3EFB635D3977E0C3F0067C1F4D255F1F87E74A8E7E4272DFDEB9B85ABBEFA4953B2E0ECAA15C3C77773155C4013955BAB0D85F
auth_key_id: 0000000000000000 0
message_id: 5607FE37D0489C00 6199202927769852928
data_length: 00000178 376
message_data: 1F5F04F54479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153DFE5001000A974C499344B093ADF321597858B1A6179E2A6C21F5FF9EB5DE687CDB57F8059509482FF9846FBE99D9411C13A645B26F73960424A13337D87DA879864FCA9D0883B643CF8EB594446038E0B6C4FD606D0CB77F1E00CCA6291DD65733F6A60217C7F366AD88972F107C381FD375F49DB57A2AB96988EC916629CD6F58B53F65DF4909AA773CCA43CE43671CA313528190213CF28A3B29BE26865BE22EB0C41E89CBD698C96CBC1B7B7F1586FBD61B422693859843F7D32083E3AB23D607FC4B874DB849F430F74483969ABA4603B483C94BCEB38F8EC90EEB58B338B325A8E37B57813CEC7E795B1B5517D732227856955C53BA18F52E55C6BCD8F1419D43D46DF2C2560B74BA7AA961BB4BDD09ABBC95E4F57AC4B8C89A67C7C5453A3EFB635D3977E0C3F0067C1F4D255F1F87E74A8E7E4272DFDEB9B85ABBEFA4953B2E0ECAA15C3C77773155C4013955BAB0D85F
message_type: F5045F1F
03:33:27.823 Send:Success:397
03:33:27.983 Receive:Success:73
03:33:27.985
....
Saludos.
A partir de febrero de 2018, puede usar un widget oficial de inicio de sesión de Telegram en su sitio web.