I want to implement multiple authorization using PHP for interaction with Telegram REST API.
What task am I trying to solve? Well, it's simple: several dozens of users (all of them have a carma like here (+10, -2, +1000 etc.) with relevant group taxonomy: web-masters and customers) have a user profile on my website. After they reach a certain amount of carma and since they are authorized in their profile they are joined to private chats based on Telegram generated for them automatically.
After some research, I found that it's very complicated because:
I took a look at https://core.telegram.org/api/auth, but it's completely unobvious how to implement these functions (for example auth.sendCode), using PHP or any other language. If these commands should be sent as JSON to server, then it doesn't look like JSON:
auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;
What is it? In which language is it written?
UPD: It's written in TL (Type Language): https://core.telegram.org/mtproto/TL
I've explored the source code of several clients (Webogram, Telegram-cli (tg), tdesktop), and I found several implementations of https://core.telegram.org/mtproto
Unfortunately, none of them support multiple authorization on their side, and after a little bit of research, I have no idea where to dig deeper to find out more information.
Also, these implementations look bulky and compound (for example, https://github.com/vysheng/tg):
There I see bunch of servers (./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"
I found several possibly appropriate functions (./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.
What files should I transfer to PHP for multiple user auth implementation? Could you please help me to know where to start from and how to make it easier than it currently is?
Thank you in advance!
When you use Telegram login for the first time, our widget asks for your phone number and sends you a confirmation message via Telegram to authorize your browser. Logging in will send your Telegram name, username, and your profile picture to the website owner.
Creating a client Before you can start interacting with the Telegram API, you need to create a client object with your api_id and api_hash and authenticate it with your phone number. This is similar to logging in to Telegram on a new device; you can imagine this client as just another Telegram app.
We offer two kinds of APIs for developers. The Bot API allows you to easily create programs that use Telegram messages for an interface. The Telegram API and TDLib allow you to build your own customized Telegram clients.
So far I have been able to implement the telegram authorization completely, but not in your requested language - PHP, I used vb.Net. However, I believe the same logic should apply.
Creating a Telegram Authorization Key
Telegram API is no walk in the park. Studying existing src code could be quite daunting (IMHO). Hence my approach was to study the online API documentation and implement the sample-auth_key outlined in the links below.
https://core.telegram.org/mtproto/auth_key
https://core.telegram.org/mtproto/samples-auth_key
What this approach will give you is a better understanding and introduction to the primitives used throughout Telegram API, and possibly help you start organizing your own set of functions and routines to handle which you will need for the next steps - implementing other features of the API, since generating an AuthKey is just the beginning.
Step 1
All Communication is via TCP - Once you have obtained a unique api_id (https://core.telegram.org/api/obtaining_api_id#obtaining-api-id) you will find the following IP advertised for use in testing: 149.154.167.40:433 The api_id is not required at this point for generating an AuthKey
Setup your preferred method of Send/Receive TCP processing Loop
what I have is a private SendData that simply sends a bytes to a live socket connected to the give IP address above
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
Finally for this step, we need a TcpPack() method which helps us pad our data in the format Telegram expects - see code below with comments
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
STEP 2
With the basic TCP send/receive routines setup, we can start preparing data packets to send to telegram and have sub routines for handling the specific responses received - ProcessResponse(data)
What we need to understand next is the fact that Telegram handles 2 broad categories of messages -
Unencrypted - https://core.telegram.org/mtproto/description#unencrypted-message
These are plain text messages with their auth_key_id =0
generating an AuthKey uses this type of message throughout
Encrypted - https://core.telegram.org/mtproto/description#encrypted-message-encrypted-data
All further communication with Telegram Servers will be via encrypted messages
I choose to have two classes to encapsulate both message types. I can then have two Send(m) methods that handles each type
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
For now only UnencryptedMessage is required
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
STEP 3
Now we follow he series of steps outlined in https://core.telegram.org/mtproto/auth_key
- Client sends query to server
req_pq#60469778 nonce:int128 = ResPQ The value of nonce is selected randomly by the client (random number) and identifies the client within this communication. Following this step, it is known to all.
- Server sends response of the form
resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector long = ResPQ
My approach for this is very simple:
Sub RequestPQAuthorization() Send(MTProto.req_pq) End Sub
In a Class called MTProto I implement a set of shared functions as required by each step of the exchange. Each method is simply building up an Encrypted data structure which will be sent as above where required
We start with: 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)
Now our process response method from Step 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
Great so far, each response received has a message_type code.
we can switch on that and determine how each is handled. We need to process resPQ right now.
What i have done is to create a a set of classes that each handles a specific response type
''' <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
Each is based on this simple object
Public MustInherit Class TLObject Public Shared Property ClassId As String Public MustOverride Overrides Function ToString() As String End Class
Building on this, we tackle steps 3 & 4
Proof of work 3) Client decomposes pq into prime factors such that p < q.
This starts a round of Diffie-Hellman key exchanges.
Presenting proof of work; Server authentication 4) Client sends query to server
req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params
This is initiated here RequestDHKeyExchange(New resPQ(r.message_data))
in my ProcessResponse
routine above
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
You can use your own implementation of Prime-Decomposition to replace this line Dim pp = New PrimeProduct(r.pq)
Here is an example of how I learnt do it using PollardBrent (Pollard Rho Brent Integer Factorization) https://stackoverflow.com/a/31978350/44080
Okay if you can follow up to this point you have a general idea of how i'm decomposing the AuthKey implementation step by step.
You should be able to run through the remaining steps 5-9. It's a lot for me to type...
If this answer so far is of any help to anyone, then i'll take out time to organize and post the remaining part.
I believe that the routines and knowledge you build up along the way should give you the tools you need to both understand and implement your own independent Telegram API code from scratch.
Completed Interaction Dump
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
....
Regards.
I have written a PHP implementation of mtproto, and so far I have managed to implement TL serialization/deserialization, tcp abridged/intermediate/full connections, http/https connections.
I have implemented OOP wrappers for all mtproto methods, a prime generation module based on Python/wolfram alpha/php, HTML/Markdown parsing with support for mentions, bot API file id support, update handling with callbacks or getupdates, bot API <-> MTProto object conversion, upload/download wrappers, login wrappers for bots/users (2FA is supported), simple error handling, internal peer management (you can provide a simple bot API chat id, a username or a peer id in tg-cli format to send a message or to call other mtproto methods) and I am currently working on a nice Lua wrapper to allow usage of td-cli/tg-cli bots w/ MadelineProto.
I have also written a class to generate documentation for all mtproto methods/constructors/types (available at https://daniil.it/MadelineProto/API_docs). MadelineProto can be serialized to a file to allow easy session storage.
If anyone is interested, or wants to contribute, here is the link to the github repo: https://github.com/danog/MadelineProto
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With