Auth key generation example

In the examples below, the transport headers are omitted:

For example, for the abridged version of the transport », the client sends 0xef as the first byte (important: only prior to the very first data packet), then the packet length is encoded with a single byte (0x01-0x7e = data length divided by 4; or 0x7f followed by 3 bytes (little endian) divided by 4) followed by the data itself. In this case, server responses have the same structure (although the server does not send 0xefas the first byte). Detailed documentation on creating authorization keys is available here ».

DH exchange initiation

1) Client sends query to server

Sent payload (excluding transport headers/trailers):

0000 | 00 00 00 00 00 00 00 00 00 4F 00 00 0C 07 3B 6A
0010 | 14 00 00 00 F1 8E 7E BE C0 D3 C5 02 57 C0 3F 46
0020 | A9 2F 75 67 16 9F 26 38

Payload (de)serialization:

req_pq_multi#00000000 nonce:int128 = ResPQ;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 004F00000C073B6A Message ID generated as specified here » (unixtime() << 32) + (N*4)
message_length 16, 4 14000000 (20 in decimal) Message body length
%(req_pq_multi) 20, 4 f18e7ebe req_pq_multi constructor number from TL schema
nonce 24, 16 C0D3C50257C03F46A92F7567169F2638 Random number
2) Server sends response of the form

Received payload (excluding transport headers/trailers):

0000 | 00 00 00 00 00 00 00 00 01 F0 4F 1D 0C 07 3B 6A
0010 | 50 00 00 00 63 24 16 05 C0 D3 C5 02 57 C0 3F 46
0020 | A9 2F 75 67 16 9F 26 38 8D 20 B1 E5 5E 0A 10 D8
0030 | DF 35 5F C3 53 A7 06 1F 08 1F C1 65 C8 53 92 F6
0040 | ED 00 00 00 15 C4 B5 1C 03 00 00 00 85 FD 64 DE
0050 | 85 1D 9D D0 A5 B7 F7 09 35 5F C3 0B 21 6B E8 6C
0060 | 02 2B B4 C3

Payload (de)serialization:

resPQ#00000000 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector<strlong> = ResPQ;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 01F04F1D0C073B6A Message ID generated as specified here » (unixtime() << 32) + (N*4)
message_length 16, 4 50000000 (80 in decimal) Message body length
%(resPQ) 20, 4 63241605 resPQ constructor number from TL schema
nonce 24, 16 C0D3C50257C03F46A92F7567169F2638 Value generated by client in Step 1
server_nonce 40, 16 8D20B1E55E0A10D8DF355FC353A7061F Server-generated random number
pq 56, 12 081FC165C85392F6ED000000
TL byte deserialization
=> bigendian conversion to decimal
=> 2288221996750927597
Single-byte prefix denoting length, an 8-byte string, and three bytes of padding
%(Vector strlong) 68, 4 15c4b51c Vector t constructor number from TL schema
count 72, 4 03000000 Number of elements in server_public_key_fingerprints
server_public_key_fingerprints[0] 76, 8 85FD64DE851D9DD0 64 lower-order bits of SHA1(server_public_key)
server_public_key_fingerprints[1] 84, 8 A5B7F709355FC30B 64 lower-order bits of SHA1(server_public_key)
server_public_key_fingerprints[2] 92, 8 216BE86C022BB4C3 64 lower-order bits of SHA1(server_public_key)

In our case, the client only has the following public keys, with the following fingerprints:

  • 85FD64DE851D9DD0

Let's choose the only matching key, the one with fingerprint equal to 85FD64DE851D9DD0.

Proof of work

3) Client decomposes pq into prime factors such that p < q.
pq = 2288221996750927597

Decompose into 2 prime cofactors p < q: 2288221996750927597 = 1298008031 * 1762871987

p = 1298008031
q = 1762871987

Presenting proof of work; Server authentication

4) encrypted_data payload generation

First of all, generate an encrypted_data payload as follows:

Generated payload (excluding transport headers/trailers):

0000 | 95 5F F5 A9 08 1F C1 65 C8 53 92 F6 ED 00 00 00
0010 | 04 4D 5E 07 DF 00 00 00 04 69 13 4A B3 00 00 00
0020 | C0 D3 C5 02 57 C0 3F 46 A9 2F 75 67 16 9F 26 38
0030 | 8D 20 B1 E5 5E 0A 10 D8 DF 35 5F C3 53 A7 06 1F
0040 | D2 7D FC 68 68 CB 29 DD 74 3E 85 80 12 1B DD 84
0050 | 6B 62 2E 1B AD 51 D4 A8 55 C6 E7 E4 DE 47 3E 84
0060 | 02 00 00 00

Payload (de)serialization:

p_q_inner_data_dc#00000000 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data;
Parameter Offset, Length in bytes Value Description
%(p_q_inner_data_dc) 0, 4 955ff5a9 p_q_inner_data_dc constructor number from TL schema
pq 4, 12 081FC165C85392F6ED000000
TL byte deserialization
=> bigendian conversion to decimal
=> 2288221996750927597
Single-byte prefix denoting length, 8-byte string, and three bytes of padding
p 16, 8 044D5E07DF000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1298008031
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 24, 8 0469134AB3000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1762871987
Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
nonce 32, 16 C0D3C50257C03F46A92F7567169F2638 Value generated by client in Step 1
server_nonce 48, 16 8D20B1E55E0A10D8DF355FC353A7061F Value received from server in Step 2
new_nonce 64, 32 D27DFC6868CB29DD743E8580121BDD84 6B622E1BAD51D4A855C6E7E4DE473E84 Client-generated random number
dc 96, 4 02000000 (2 in decimal) DC ID: 10000 (decimal) has to be added to the DC ID to connect to the test servers; it has to be made negative if the DC we're connecting to is a media (not CDN) DC.

The serialization of P_Q_inner_data produces data, which is used to generate encrypted_data as specified in step 4.1.
These are the inputs to the algorithm specified in step 4.1:

data = 955FF5A9081FC165C85392F6ED000000044D5E07DF0000000469134AB3000000C0D3C50257C03F46A92F7567169F26388D20B1E55E0A10D8DF355FC353A7061FD27DFC6868CB29DD743E8580121BDD846B622E1BAD51D4A855C6E7E4DE473E8402000000
random_padding_bytes = C6F6E6158328837183990F0A081DF48C98CFF5F4EA6802C711AE16D89722E1F24469E85F7B30E27068D9D246BBDC36CC94DD6350BC636253D4B2448B0C216CE71DDF1A2FD7D714CAEC6ED8C56FCE6EAAD2CD12129824D2BA559672DE

And this is the output:

encrypted_data = 2800671C92D660F5A306565754EA6E6FFCC08DB9B331CD84DC9A496B2F31EA1D0E5271433D5858A60F1BEFE0A16BC1E33408D8D1C1C5D3E29327DF2BB6C77EECC2A263CD0194EF3B488FEB8A8B3750CB955D244A104C06BAA5FB91C2E807E31290527A55EB13FDC10EE8DF113534FB3DBC6C09784CA78F60969F0416E79A0E5A161A8C5ED7DD6FA1E24CCFA262DF1B63B2A6778440EF47A1AAA0578E43075E73E0B2A9A94206F8A3E45CA6C976223E979E69AF5E6867599E7222F1C402DAC7D215C8A090A16AD204A0C554A5496A13CD4B400B2E6204F5CCD344171B5C2F026C4AB81B9CE9F88A58EB8146CA0738F2E1A794E16931C5BC91B908E49C8CF57217

The length of the final string is 256 bytes.

5) Send req_DH_params query with generated encrypted_data

Sent payload (excluding transport headers/trailers):

0000 | 00 00 00 00 00 00 00 00 68 8A 06 00 0C 07 3B 6A
0010 | 40 01 00 00 BE E4 12 D7 C0 D3 C5 02 57 C0 3F 46
0020 | A9 2F 75 67 16 9F 26 38 8D 20 B1 E5 5E 0A 10 D8
0030 | DF 35 5F C3 53 A7 06 1F 04 4D 5E 07 DF 00 00 00
0040 | 04 69 13 4A B3 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 28 00 67 1C 92 D6 60 F5 A3 06 56 57
0060 | 54 EA 6E 6F FC C0 8D B9 B3 31 CD 84 DC 9A 49 6B
0070 | 2F 31 EA 1D 0E 52 71 43 3D 58 58 A6 0F 1B EF E0
0080 | A1 6B C1 E3 34 08 D8 D1 C1 C5 D3 E2 93 27 DF 2B
0090 | B6 C7 7E EC C2 A2 63 CD 01 94 EF 3B 48 8F EB 8A
00A0 | 8B 37 50 CB 95 5D 24 4A 10 4C 06 BA A5 FB 91 C2
00B0 | E8 07 E3 12 90 52 7A 55 EB 13 FD C1 0E E8 DF 11
00C0 | 35 34 FB 3D BC 6C 09 78 4C A7 8F 60 96 9F 04 16
00D0 | E7 9A 0E 5A 16 1A 8C 5E D7 DD 6F A1 E2 4C CF A2
00E0 | 62 DF 1B 63 B2 A6 77 84 40 EF 47 A1 AA A0 57 8E
00F0 | 43 07 5E 73 E0 B2 A9 A9 42 06 F8 A3 E4 5C A6 C9
0100 | 76 22 3E 97 9E 69 AF 5E 68 67 59 9E 72 22 F1 C4
0110 | 02 DA C7 D2 15 C8 A0 90 A1 6A D2 04 A0 C5 54 A5
0120 | 49 6A 13 CD 4B 40 0B 2E 62 04 F5 CC D3 44 17 1B
0130 | 5C 2F 02 6C 4A B8 1B 9C E9 F8 8A 58 EB 81 46 CA
0140 | 07 38 F2 E1 A7 94 E1 69 31 C5 BC 91 B9 08 E4 9C
0150 | 8C F5 72 17

Payload (de)serialization:

req_DH_params#00000000 nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 688A06000C073B6A Message ID generated as specified here » (unixtime() << 32) + (N*4)
message_length 16, 4 40010000 (320 in decimal) Message body length
%(req_DH_params) 20, 4 bee412d7 req_DH_params constructor number from TL schema
nonce 24, 16 C0D3C50257C03F46A92F7567169F2638 Value generated by client in Step 1
server_nonce 40, 16 8D20B1E55E0A10D8DF355FC353A7061F Value received from server in Step 2
p 56, 8 044D5E07DF000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1298008031
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 64, 8 0469134AB3000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1762871987
Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
public_key_fingerprint 72, 8 85FD64DE851D9DD0 fingerprint of public key used
encrypted_data 80, 260 FE0001002800671C92D660F5A3065657 54EA6E6FFCC08DB9B331CD84DC9A496B 2F31EA1D0E5271433D5858A60F1BEFE0 A16BC1E33408D8D1C1C5D3E29327DF2B B6C77EECC2A263CD0194EF3B488FEB8A 8B3750CB955D244A104C06BAA5FB91C2 E807E31290527A55EB13FDC10EE8DF11 3534FB3DBC6C09784CA78F60969F0416 E79A0E5A161A8C5ED7DD6FA1E24CCFA2 62DF1B63B2A6778440EF47A1AAA0578E 43075E73E0B2A9A94206F8A3E45CA6C9 76223E979E69AF5E6867599E7222F1C4 02DAC7D215C8A090A16AD204A0C554A5 496A13CD4B400B2E6204F5CCD344171B 5C2F026C4AB81B9CE9F88A58EB8146CA 0738F2E1A794E16931C5BC91B908E49C
8CF57217
Value generated above
6) Server responds with:

Received payload (excluding transport headers/trailers):

0000 | 00 00 00 00 00 00 00 00 01 9C 7B 4B 0C 07 3B 6A
0010 | 78 02 00 00 5C 07 E8 D0 C0 D3 C5 02 57 C0 3F 46
0020 | A9 2F 75 67 16 9F 26 38 8D 20 B1 E5 5E 0A 10 D8
0030 | DF 35 5F C3 53 A7 06 1F FE 50 02 00 C4 5B 7E DE
0040 | D0 AD 2A D6 7C 50 07 82 DE 38 65 EA A2 4A 81 DF
0050 | 05 12 B2 E6 73 61 76 8E 04 E2 00 3D 32 09 96 A6
0060 | C6 10 9D 22 64 74 0E FA A1 2F 5F 8C 89 F2 59 1A
0070 | 24 BD 82 9B 7D C1 F9 70 EB E0 EB 7E 97 E2 A1 9F
0080 | CB 70 82 DE 47 AC 24 FD 8B F5 2D CC C8 81 1D C0
0090 | 7C 70 91 E9 AA 79 AE 57 AE 5D 9F 96 D4 7C AC C0
00A0 | 65 EB 5C 14 11 29 D1 CB 1B F9 B0 A1 D9 ED BA 0F
00B0 | 8C 85 09 F1 0B 84 9B 9C 0E E2 0D 9C 47 8F EB AC
00C0 | DC 5C 2D 77 A5 7F F6 10 10 39 BB 0F DD 4D C0 7E
00D0 | 71 76 85 8A 52 3A 0C 90 78 A2 39 CD 7D 45 F4 67
00E0 | 10 B2 4E 18 DC 0A 36 CA 88 7B C8 E5 DD 1D A7 04
00F0 | A8 EA 50 B0 FB 94 95 BB 6B 98 6E 95 01 0C 18 58
0100 | 67 B5 9D CA BA DB B9 28 17 C8 AA 90 90 36 AD 75
0110 | 8F 11 2E AF 71 E4 54 03 96 3C 1F 18 31 2F 54 ED
0120 | 99 78 6C 83 9B 9D BB DF FD 98 9C 29 6B AD B6 F4
0130 | E3 F9 2B 7F F8 6A B6 07 04 EE 5D 5A D4 9F AA 52
0140 | 50 A1 90 B9 FE 74 1E A0 48 15 42 4F B5 80 51 51
0150 | C7 F5 10 ED 35 F2 40 7B 0C 0F 9F 3F 38 72 7C 4B
0160 | 65 2A 8F BA F3 CA 17 9A A1 B4 44 B6 AD 04 D0 58
0170 | B9 F9 CD 25 9F 2F FB BF 09 B4 DC C0 91 DE 77 08
0180 | 93 E3 76 A4 C5 52 D1 21 BD 28 77 49 9A 6F A3 7D
0190 | D1 B0 85 D4 71 C6 0C E7 50 04 50 D9 51 7C 6E FD
01A0 | 9A 75 8C 91 AB 15 E7 CE 30 A5 6A DF 35 BF C3 A0
01B0 | 7F 18 C9 04 0A 5D 7F 4B 27 7E 43 3B 6E 04 DA 9E
01C0 | 99 6A 71 D5 EE B8 4A 68 44 BC E6 8B A9 6C 6B 72
01D0 | 36 BC 71 A7 4D 2B F8 78 70 F6 E6 D6 07 3A 64 CF
01E0 | BB 59 7E B2 70 BD C5 87 1E B9 BD 1D 93 98 00 D2
01F0 | 97 C6 0E 25 5C E8 5A 13 59 24 35 C4 EB 8D CD 49
0200 | 50 89 F6 15 D4 52 51 85 08 A5 90 18 0D E2 25 53
0210 | D9 FB 38 B4 14 FC 9E DE 48 9E 01 76 78 98 D9 D9
0220 | 2C 39 33 FB DE EC 15 F5 12 62 2F A6 D7 EB 31 F7
0230 | A2 F4 31 CC EE D6 FF 0D 3F F9 30 51 6E 62 D4 60
0240 | 0A C4 DE 45 F2 CD 96 8A 32 FB C9 45 F3 90 D1 5D
0250 | C4 5E BD AE 75 D3 DE 21 B3 DA F9 5E 86 3C A9 06
0260 | 48 44 82 68 C4 29 91 3B 65 5F DE 01 BF 05 1F 00
0270 | 76 3D BA 1E 44 2B 45 AE E4 63 F9 E0 B9 03 78 3D
0280 | 83 53 4C EC 86 98 08 43 5D BC 73 FB

Payload (de)serialization:

server_DH_params_ok#00000000 nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 019C7B4B0C073B6A Message ID generated as specified here » (unixtime() << 32) + (N*4)
message_length 16, 4 78020000 (632 in decimal) Message body length
%(server_DH_params_ok) 20, 4 5c07e8d0 server_DH_params_ok constructor number from TL schema
nonce 24, 16 C0D3C50257C03F46A92F7567169F2638 Value generated by client in Step 1
server_nonce 40, 16 8D20B1E55E0A10D8DF355FC353A7061F Value received from server in Step 2
encrypted_answer 56, 596 FE500200C45B7EDED0AD2AD67C500782 DE3865EAA24A81DF0512B2E67361768E 04E2003D320996A6C6109D2264740EFA A12F5F8C89F2591A24BD829B7DC1F970 EBE0EB7E97E2A19FCB7082DE47AC24FD 8BF52DCCC8811DC07C7091E9AA79AE57 AE5D9F96D47CACC065EB5C141129D1CB 1BF9B0A1D9EDBA0F8C8509F10B849B9C 0EE20D9C478FEBACDC5C2D77A57FF610 1039BB0FDD4DC07E7176858A523A0C90 78A239CD7D45F46710B24E18DC0A36CA 887BC8E5DD1DA704A8EA50B0FB9495BB 6B986E95010C185867B59DCABADBB928 17C8AA909036AD758F112EAF71E45403 963C1F18312F54ED99786C839B9DBBDF FD989C296BADB6F4E3F92B7FF86AB607 04EE5D5AD49FAA5250A190B9FE741EA0 4815424FB5805151C7F510ED35F2407B 0C0F9F3F38727C4B652A8FBAF3CA179A A1B444B6AD04D058B9F9CD259F2FFBBF 09B4DCC091DE770893E376A4C552D121 BD2877499A6FA37DD1B085D471C60CE7 500450D9517C6EFD9A758C91AB15E7CE 30A56ADF35BFC3A07F18C9040A5D7F4B 277E433B6E04DA9E996A71D5EEB84A68 44BCE68BA96C6B7236BC71A74D2BF878 70F6E6D6073A64CFBB597EB270BDC587 1EB9BD1D939800D297C60E255CE85A13 592435C4EB8DCD495089F615D4525185 08A590180DE22553D9FB38B414FC9EDE 489E01767898D9D92C3933FBDEEC15F5 12622FA6D7EB31F7A2F431CCEED6FF0D 3FF930516E62D4600AC4DE45F2CD968A 32FBC945F390D15DC45EBDAE75D3DE21 B3DAF95E863CA90648448268C429913B 655FDE01BF051F00763DBA1E442B45AE E463F9E0B903783D83534CEC86980843
5DBC73FB
See below

Decrypt encrypted_answer using the reverse of the process specified in step 6:

encrypted_answer = C45B7EDED0AD2AD67C500782DE3865EAA24A81DF0512B2E67361768E04E2003D320996A6C6109D2264740EFAA12F5F8C89F2591A24BD829B7DC1F970EBE0EB7E97E2A19FCB7082DE47AC24FD8BF52DCCC8811DC07C7091E9AA79AE57AE5D9F96D47CACC065EB5C141129D1CB1BF9B0A1D9EDBA0F8C8509F10B849B9C0EE20D9C478FEBACDC5C2D77A57FF6101039BB0FDD4DC07E7176858A523A0C9078A239CD7D45F46710B24E18DC0A36CA887BC8E5DD1DA704A8EA50B0FB9495BB6B986E95010C185867B59DCABADBB92817C8AA909036AD758F112EAF71E45403963C1F18312F54ED99786C839B9DBBDFFD989C296BADB6F4E3F92B7FF86AB60704EE5D5AD49FAA5250A190B9FE741EA04815424FB5805151C7F510ED35F2407B0C0F9F3F38727C4B652A8FBAF3CA179AA1B444B6AD04D058B9F9CD259F2FFBBF09B4DCC091DE770893E376A4C552D121BD2877499A6FA37DD1B085D471C60CE7500450D9517C6EFD9A758C91AB15E7CE30A56ADF35BFC3A07F18C9040A5D7F4B277E433B6E04DA9E996A71D5EEB84A6844BCE68BA96C6B7236BC71A74D2BF87870F6E6D6073A64CFBB597EB270BDC5871EB9BD1D939800D297C60E255CE85A13592435C4EB8DCD495089F615D452518508A590180DE22553D9FB38B414FC9EDE489E01767898D9D92C3933FBDEEC15F512622FA6D7EB31F7A2F431CCEED6FF0D3FF930516E62D4600AC4DE45F2CD968A32FBC945F390D15DC45EBDAE75D3DE21B3DAF95E863CA90648448268C429913B655FDE01BF051F00763DBA1E442B45AEE463F9E0B903783D83534CEC869808435DBC73FB
tmp_aes_key = 00AFAD030EBA2B93EB7AF03BDB757660A1A9872488A721C7BF070AB47F0FC109
tmp_aes_iv = C1F342AC607D8B3826A62C29FA4D4C176AE2ECE7DD92EA5DEA5A978DD27DFC68

Yielding:

answer_with_hash = 42A822E611133C0296CCC360CFE6B72E833AE886BA0D89B5C0D3C50257C03F46A92F7567169F26388D20B1E55E0A10D8DF355FC353A7061F03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE000100401D382927223B1746D744855D26BB2975792B40E5AECF3503F2652948B0FC036C495D640A41516BFE78232C155EF5A62711DE64BD9B076CB76D5B5F27C8B6A17649AB5973D6F8A4B444D57AD2D9909E998F8387F4CECE3EC20F7AB755EAEF989D0BC1806E7F5A2AA916814C966B9B263A30CFB6B5D9A0EEE760D202C4364434AA34819FFCE743B6765D0B122B0123E9C2E85E123B0F96A96559D40D27CBD803E65D7B8EA90A2B1E859CC161522F0100941804BBAD695E80634C7BC9DB6A74F68E9C72DDE4A695EADB421F10B73C1635812E62F4F077A9643A436662B2592830DFCA974C041A2E9C11F31AAE9A4D8CD4535EDEA50B766ACC8AFB754B1EF1982E0C073B6A80A714E5E010EC38
answer = BA0D89B5C0D3C50257C03F46A92F7567169F26388D20B1E55E0A10D8DF355FC353A7061F03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE000100401D382927223B1746D744855D26BB2975792B40E5AECF3503F2652948B0FC036C495D640A41516BFE78232C155EF5A62711DE64BD9B076CB76D5B5F27C8B6A17649AB5973D6F8A4B444D57AD2D9909E998F8387F4CECE3EC20F7AB755EAEF989D0BC1806E7F5A2AA916814C966B9B263A30CFB6B5D9A0EEE760D202C4364434AA34819FFCE743B6765D0B122B0123E9C2E85E123B0F96A96559D40D27CBD803E65D7B8EA90A2B1E859CC161522F0100941804BBAD695E80634C7BC9DB6A74F68E9C72DDE4A695EADB421F10B73C1635812E62F4F077A9643A436662B2592830DFCA974C041A2E9C11F31AAE9A4D8CD4535EDEA50B766ACC8AFB754B1EF1982E0C073B6A80A714E5E010EC38

Generated payload (excluding transport headers/trailers):

0000 | BA 0D 89 B5 C0 D3 C5 02 57 C0 3F 46 A9 2F 75 67
0010 | 16 9F 26 38 8D 20 B1 E5 5E 0A 10 D8 DF 35 5F C3
0020 | 53 A7 06 1F 03 00 00 00 FE 00 01 00 C7 1C AE B9
0030 | C6 B1 C9 04 8E 6C 52 2F 70 F1 3F 73 98 0D 40 23
0040 | 8E 3E 21 C1 49 34 D0 37 56 3D 93 0F 48 19 8A 0A
0050 | A7 C1 40 58 22 94 93 D2 25 30 F4 DB FA 33 6F 6E
0060 | 0A C9 25 13 95 43 AE D4 4C CE 7C 37 20 FD 51 F6
0070 | 94 58 70 5A C6 8C D4 FE 6B 6B 13 AB DC 97 46 51
0080 | 29 69 32 84 54 F1 8F AF 8C 59 5F 64 24 77 FE 96
0090 | BB 2A 94 1D 5B CD 1D 4A C8 CC 49 88 07 08 FA 9B
00A0 | 37 8E 3C 4F 3A 90 60 BE E6 7C F9 A4 A4 A6 95 81
00B0 | 10 51 90 7E 16 27 53 B5 6B 0F 6B 41 0D BA 74 D8
00C0 | A8 4B 2A 14 B3 14 4E 0E F1 28 47 54 FD 17 ED 95
00D0 | 0D 59 65 B4 B9 DD 46 58 2D B1 17 8D 16 9C 6B C4
00E0 | 65 B0 D6 FF 9C A3 92 8F EF 5B 9A E4 E4 18 FC 15
00F0 | E8 3E BE A0 F8 7F A9 FF 5E ED 70 05 0D ED 28 49
0100 | F4 7B F9 59 D9 56 85 0C E9 29 85 1F 0D 81 15 F6
0110 | 35 B1 05 EE 2E 4E 15 D0 4B 24 54 BF 6F 4F AD F0
0120 | 34 B1 04 03 11 9C D8 E3 B9 2F CC 5B FE 00 01 00
0130 | 40 1D 38 29 27 22 3B 17 46 D7 44 85 5D 26 BB 29
0140 | 75 79 2B 40 E5 AE CF 35 03 F2 65 29 48 B0 FC 03
0150 | 6C 49 5D 64 0A 41 51 6B FE 78 23 2C 15 5E F5 A6
0160 | 27 11 DE 64 BD 9B 07 6C B7 6D 5B 5F 27 C8 B6 A1
0170 | 76 49 AB 59 73 D6 F8 A4 B4 44 D5 7A D2 D9 90 9E
0180 | 99 8F 83 87 F4 CE CE 3E C2 0F 7A B7 55 EA EF 98
0190 | 9D 0B C1 80 6E 7F 5A 2A A9 16 81 4C 96 6B 9B 26
01A0 | 3A 30 CF B6 B5 D9 A0 EE E7 60 D2 02 C4 36 44 34
01B0 | AA 34 81 9F FC E7 43 B6 76 5D 0B 12 2B 01 23 E9
01C0 | C2 E8 5E 12 3B 0F 96 A9 65 59 D4 0D 27 CB D8 03
01D0 | E6 5D 7B 8E A9 0A 2B 1E 85 9C C1 61 52 2F 01 00
01E0 | 94 18 04 BB AD 69 5E 80 63 4C 7B C9 DB 6A 74 F6
01F0 | 8E 9C 72 DD E4 A6 95 EA DB 42 1F 10 B7 3C 16 35
0200 | 81 2E 62 F4 F0 77 A9 64 3A 43 66 62 B2 59 28 30
0210 | DF CA 97 4C 04 1A 2E 9C 11 F3 1A AE 9A 4D 8C D4
0220 | 53 5E DE A5 0B 76 6A CC 8A FB 75 4B 1E F1 98 2E
0230 | 0C 07 3B 6A

Payload (de)serialization:

server_DH_inner_data#00000000 nonce:int128 server_nonce:int128 g:int dh_prime:string g_a:string server_time:int = Server_DH_inner_data;
Parameter Offset, Length in bytes Value Description
%(server_DH_inner_data) 0, 4 ba0d89b5 server_DH_inner_data constructor number from TL schema
nonce 4, 16 C0D3C50257C03F46A92F7567169F2638 Value generated by client in Step 1
server_nonce 20, 16 8D20B1E55E0A10D8DF355FC353A7061F Value received from server in Step 2
g 36, 4 03000000 (3 in decimal) Value received from server in Step 2
dh_prime 40, 260 FE000100C71CAEB9C6B1C9048E6C522F 70F13F73980D40238E3E21C14934D037 563D930F48198A0AA7C14058229493D2 2530F4DBFA336F6E0AC925139543AED4 4CCE7C3720FD51F69458705AC68CD4FE 6B6B13ABDC9746512969328454F18FAF 8C595F642477FE96BB2A941D5BCD1D4A C8CC49880708FA9B378E3C4F3A9060BE E67CF9A4A4A695811051907E162753B5 6B0F6B410DBA74D8A84B2A14B3144E0E F1284754FD17ED950D5965B4B9DD4658 2DB1178D169C6BC465B0D6FF9CA3928F EF5B9AE4E418FC15E83EBEA0F87FA9FF 5EED70050DED2849F47BF959D956850C E929851F0D8115F635B105EE2E4E15D0 4B2454BF6F4FADF034B10403119CD8E3
B92FCC5B
2048-bit prime, in big-endian byte order, to be checked as specified in the auth key docs
g_a 300, 260 FE000100401D382927223B1746D74485 5D26BB2975792B40E5AECF3503F26529 48B0FC036C495D640A41516BFE78232C 155EF5A62711DE64BD9B076CB76D5B5F 27C8B6A17649AB5973D6F8A4B444D57A D2D9909E998F8387F4CECE3EC20F7AB7 55EAEF989D0BC1806E7F5A2AA916814C 966B9B263A30CFB6B5D9A0EEE760D202 C4364434AA34819FFCE743B6765D0B12 2B0123E9C2E85E123B0F96A96559D40D 27CBD803E65D7B8EA90A2B1E859CC161 522F0100941804BBAD695E80634C7BC9 DB6A74F68E9C72DDE4A695EADB421F10 B73C1635812E62F4F077A9643A436662 B2592830DFCA974C041A2E9C11F31AAE 9A4D8CD4535EDEA50B766ACC8AFB754B
1EF1982E
g_a diffie-hellman parameter
server_time 560, 4 0C073B6A (1782253324 in decimal) Server time
7) Client computes random 2048-bit number b (using a sufficient amount of entropy) and sends the server a message

First, generate a secure random 2048-bit number b:

b = 061866FDE4323F9740DC49BC21AF1D9834C208B7F5B204B3A04E49FE28A04EA9CA33D4659D291FD10A9A4BBD162BF1146F34B0DBF399F6CBAA9860686290DBE9145CD91AFC90A371890B603B006EB6BF65A921353053D0EBA2F4849C80A6E1D1679C3F8D7D3FE60C085065A7A3ED3E74D920ECAA0B26D61355A7913C3D6EC0C2BA306D04657F096FCE03116DF3DDE253FE0D32D3B4295CA87AB86CE632589BCEF9936722DD3DAAC34669AC8519FC7BE7C03DC4AA19B014E4C9880EA354BF152E765209D12C880DEA046E28D97C62BA678457D86862EC274AF3DC1020B227B2AB134AB4362FB72150134B008C02F1082AEA265AAC605B075596EFE2A0C1970DC5

Then compute g_b = pow(g, b) mod dh_prime

g_b = 14A02FF2B6945A99C8366E6DB52DE4DEE1C620837CFC9888353F70F89145E59CB35C5FFBE63AEA40D57D9F2525561D4A0756E3A59B85781B8729A0626274210D5985C54493AAD1AC2088706B1A693A3840393B4F6BDA34C6478B2C0F1DE694B573CF7451ABAFA2E875F8B6AA2059B7CE4CDF9B966649323E455D3F5453B344A7F81C88C065B37F3F22824D7C04FFAE7B514027F373902FE09E06DF79E4E8CD921A372CB2F255D94BA05555A9141CE288FFF9FD9E71AE221B0B140922E9F4D691C2169013CE7ADF5C3CF0B7FB52519688DCA99125385C445F5D5C3EBD8A95A1A584600AF3D064B7A976ED6C8B112D17D53709D416CB445F0F726DE5D3A8F889BD
7.1) generation of encrypted_data

Generated payload (excluding transport headers/trailers):

0000 | 54 B6 43 66 C0 D3 C5 02 57 C0 3F 46 A9 2F 75 67
0010 | 16 9F 26 38 8D 20 B1 E5 5E 0A 10 D8 DF 35 5F C3
0020 | 53 A7 06 1F 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | 14 A0 2F F2 B6 94 5A 99 C8 36 6E 6D B5 2D E4 DE
0040 | E1 C6 20 83 7C FC 98 88 35 3F 70 F8 91 45 E5 9C
0050 | B3 5C 5F FB E6 3A EA 40 D5 7D 9F 25 25 56 1D 4A
0060 | 07 56 E3 A5 9B 85 78 1B 87 29 A0 62 62 74 21 0D
0070 | 59 85 C5 44 93 AA D1 AC 20 88 70 6B 1A 69 3A 38
0080 | 40 39 3B 4F 6B DA 34 C6 47 8B 2C 0F 1D E6 94 B5
0090 | 73 CF 74 51 AB AF A2 E8 75 F8 B6 AA 20 59 B7 CE
00A0 | 4C DF 9B 96 66 49 32 3E 45 5D 3F 54 53 B3 44 A7
00B0 | F8 1C 88 C0 65 B3 7F 3F 22 82 4D 7C 04 FF AE 7B
00C0 | 51 40 27 F3 73 90 2F E0 9E 06 DF 79 E4 E8 CD 92
00D0 | 1A 37 2C B2 F2 55 D9 4B A0 55 55 A9 14 1C E2 88
00E0 | FF F9 FD 9E 71 AE 22 1B 0B 14 09 22 E9 F4 D6 91
00F0 | C2 16 90 13 CE 7A DF 5C 3C F0 B7 FB 52 51 96 88
0100 | DC A9 91 25 38 5C 44 5F 5D 5C 3E BD 8A 95 A1 A5
0110 | 84 60 0A F3 D0 64 B7 A9 76 ED 6C 8B 11 2D 17 D5
0120 | 37 09 D4 16 CB 44 5F 0F 72 6D E5 D3 A8 F8 89 BD

Payload (de)serialization:

client_DH_inner_data#00000000 nonce:int128 server_nonce:int128 retry_id:long g_b:string = Client_DH_Inner_Data;
Parameter Offset, Length in bytes Value Description
%(client_DH_inner_data) 0, 4 54b64366 client_DH_inner_data constructor number from TL schema
nonce 4, 16 C0D3C50257C03F46A92F7567169F2638 Value generated by client in Step 1
server_nonce 20, 16 8D20B1E55E0A10D8DF355FC353A7061F Value received from server in Step 2
g_b 36, 260 FE00010014A02FF2B6945A99C8366E6D B52DE4DEE1C620837CFC9888353F70F8 9145E59CB35C5FFBE63AEA40D57D9F25 25561D4A0756E3A59B85781B8729A062 6274210D5985C54493AAD1AC2088706B 1A693A3840393B4F6BDA34C6478B2C0F 1DE694B573CF7451ABAFA2E875F8B6AA 2059B7CE4CDF9B966649323E455D3F54 53B344A7F81C88C065B37F3F22824D7C 04FFAE7B514027F373902FE09E06DF79 E4E8CD921A372CB2F255D94BA05555A9 141CE288FFF9FD9E71AE221B0B140922 E9F4D691C2169013CE7ADF5C3CF0B7FB 52519688DCA99125385C445F5D5C3EBD 8A95A1A584600AF3D064B7A976ED6C8B 112D17D53709D416CB445F0F726DE5D3
A8F889BD
Single-byte prefix denoting length, a 256-byte (2048-bit) string, and zero bytes of padding
retry_id 296, 8 0000000000000000 Equal to zero at the time of the first attempt; otherwise, it is equal to auth_key_aux_hash from the previous failed attempt (see Item 7).

The serialization of Client_DH_Inner_Data produces a string data. This is used to generate encrypted_data as specified in step 6, using the following inputs:

data = 54B64366C0D3C50257C03F46A92F7567169F26388D20B1E55E0A10D8DF355FC353A7061F0000000000000000FE00010014A02FF2B6945A99C8366E6DB52DE4DEE1C620837CFC9888353F70F89145E59CB35C5FFBE63AEA40D57D9F2525561D4A0756E3A59B85781B8729A0626274210D5985C54493AAD1AC2088706B1A693A3840393B4F6BDA34C6478B2C0F1DE694B573CF7451ABAFA2E875F8B6AA2059B7CE4CDF9B966649323E455D3F5453B344A7F81C88C065B37F3F22824D7C04FFAE7B514027F373902FE09E06DF79E4E8CD921A372CB2F255D94BA05555A9141CE288FFF9FD9E71AE221B0B140922E9F4D691C2169013CE7ADF5C3CF0B7FB52519688DCA99125385C445F5D5C3EBD8A95A1A584600AF3D064B7A976ED6C8B112D17D53709D416CB445F0F726DE5D3A8F889BD
padding = 364F79F457EDDD66D88A824E
tmp_aes_key = 00AFAD030EBA2B93EB7AF03BDB757660A1A9872488A721C7BF070AB47F0FC109
tmp_aes_iv = C1F342AC607D8B3826A62C29FA4D4C176AE2ECE7DD92EA5DEA5A978DD27DFC68

Process:

data_with_hash := SHA1(data) + data + padding (0-15 random bytes such that total length is divisible by 16)
encrypted_data := AES256_ige_encrypt (data_with_hash, tmp_aes_key, tmp_aes_iv);

Output:

encrypted_data = 7EC720D6487FEB7F76103EBB386F453F7B088B32E4FA998E030F2C121908AD077D4B702D877DC15A36313A8A8CABE34F32BFF1279EE03F608DF0E4775242F51B37CA8E9E140704A045DDDB57E084111BCDDBE682096F61570B315D61A026B5C8A0ADDE134D194D5A8142B3B01A0BB9CE38F0182880C8A0622BAA4D42606BB12443F95F051A48EF3F9CD9DAD36A070356D7772913D0A19B6681598F7A1B0D93ADD9C4F70385FA7C65FF00ED7D0DA0834FD079ABC4CFBBC4E0A9FB40FA93C0B32BB6644FC3CD38876912B2BE4A9648BE09EA666CEDCC28EC1AD8E05E356955D342D57EC91F30256B86D2DC4865148F8B7074C27EBFF4E2F141FF560A46D57AE351E3A9FBC435340DBB7D9CACB3BB8AE0CB4242788C6F50B6B0CCACE858CE333BD2212B87E1E166445CC497E695D488D4A0716022A281AC1C28FC931C2F197F3E5ECF5E6C442E037DC2ADB5A43121F777E3

The length of the final string is 336 bytes.

7.2) set_client_DH_params query

Sent payload (excluding transport headers/trailers):

0000 | 00 00 00 00 00 00 00 00 6C 8A 06 00 0C 07 3B 6A
0010 | 78 01 00 00 1F 5F 04 F5 C0 D3 C5 02 57 C0 3F 46
0020 | A9 2F 75 67 16 9F 26 38 8D 20 B1 E5 5E 0A 10 D8
0030 | DF 35 5F C3 53 A7 06 1F FE 50 01 00 7E C7 20 D6
0040 | 48 7F EB 7F 76 10 3E BB 38 6F 45 3F 7B 08 8B 32
0050 | E4 FA 99 8E 03 0F 2C 12 19 08 AD 07 7D 4B 70 2D
0060 | 87 7D C1 5A 36 31 3A 8A 8C AB E3 4F 32 BF F1 27
0070 | 9E E0 3F 60 8D F0 E4 77 52 42 F5 1B 37 CA 8E 9E
0080 | 14 07 04 A0 45 DD DB 57 E0 84 11 1B CD DB E6 82
0090 | 09 6F 61 57 0B 31 5D 61 A0 26 B5 C8 A0 AD DE 13
00A0 | 4D 19 4D 5A 81 42 B3 B0 1A 0B B9 CE 38 F0 18 28
00B0 | 80 C8 A0 62 2B AA 4D 42 60 6B B1 24 43 F9 5F 05
00C0 | 1A 48 EF 3F 9C D9 DA D3 6A 07 03 56 D7 77 29 13
00D0 | D0 A1 9B 66 81 59 8F 7A 1B 0D 93 AD D9 C4 F7 03
00E0 | 85 FA 7C 65 FF 00 ED 7D 0D A0 83 4F D0 79 AB C4
00F0 | CF BB C4 E0 A9 FB 40 FA 93 C0 B3 2B B6 64 4F C3
0100 | CD 38 87 69 12 B2 BE 4A 96 48 BE 09 EA 66 6C ED
0110 | CC 28 EC 1A D8 E0 5E 35 69 55 D3 42 D5 7E C9 1F
0120 | 30 25 6B 86 D2 DC 48 65 14 8F 8B 70 74 C2 7E BF
0130 | F4 E2 F1 41 FF 56 0A 46 D5 7A E3 51 E3 A9 FB C4
0140 | 35 34 0D BB 7D 9C AC B3 BB 8A E0 CB 42 42 78 8C
0150 | 6F 50 B6 B0 CC AC E8 58 CE 33 3B D2 21 2B 87 E1
0160 | E1 66 44 5C C4 97 E6 95 D4 88 D4 A0 71 60 22 A2
0170 | 81 AC 1C 28 FC 93 1C 2F 19 7F 3E 5E CF 5E 6C 44
0180 | 2E 03 7D C2 AD B5 A4 31 21 F7 77 E3

Payload (de)serialization:

set_client_DH_params#00000000 nonce:int128 server_nonce:int128 encrypted_data:string = Set_client_DH_params_answer;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 6C8A06000C073B6A Message ID generated as specified here » (unixtime() << 32) + (N*4)
message_length 16, 4 78010000 (376 in decimal) Message body length
%(set_client_DH_params) 20, 4 1f5f04f5 set_client_DH_params constructor number from TL schema
nonce 24, 16 C0D3C50257C03F46A92F7567169F2638 Value generated by client in Step 1
server_nonce 40, 16 8D20B1E55E0A10D8DF355FC353A7061F Value received from server in Step 2
encrypted_data 56, 340 FE5001007EC720D6487FEB7F76103EBB 386F453F7B088B32E4FA998E030F2C12 1908AD077D4B702D877DC15A36313A8A 8CABE34F32BFF1279EE03F608DF0E477 5242F51B37CA8E9E140704A045DDDB57 E084111BCDDBE682096F61570B315D61 A026B5C8A0ADDE134D194D5A8142B3B0 1A0BB9CE38F0182880C8A0622BAA4D42 606BB12443F95F051A48EF3F9CD9DAD3 6A070356D7772913D0A19B6681598F7A 1B0D93ADD9C4F70385FA7C65FF00ED7D 0DA0834FD079ABC4CFBBC4E0A9FB40FA 93C0B32BB6644FC3CD38876912B2BE4A 9648BE09EA666CEDCC28EC1AD8E05E35 6955D342D57EC91F30256B86D2DC4865 148F8B7074C27EBFF4E2F141FF560A46 D57AE351E3A9FBC435340DBB7D9CACB3 BB8AE0CB4242788C6F50B6B0CCACE858 CE333BD2212B87E1E166445CC497E695 D488D4A0716022A281AC1C28FC931C2F 197F3E5ECF5E6C442E037DC2ADB5A431
21F777E3
Encrypted client_DH_inner_data generated previously, serialized as a TL byte string
8) Auth key generation

The client computes the auth_key using formula g_a^b mod dh_prime:

auth_key = B74460783F3F32EA67DC96D3723A63C4B5E9E2A3454BD2CA04A1810BDCC6C5A397ADE8CA401405E5D10097708B623E51912474A459BFFB66F6FD76E6AF813C3D5BEF75526BD35772DB47BF298FF116CDE423C3D5F1830A000C266495CAE8F2A003F45ADB7D34144BF677FA2017902DB9C08F7D89A8AD7AEB759A3258F563D409B9A223D55DE41F7E11172FE3C81BD8BAF8F53152C664838A8E2E824C9F32EB8FB2BE38EEEC10037D0ECCADE3D75380C0F6375F19BE38CC603B785F83904CE06AB63A056090D227C41F0FCEC50C07B957F845975DACB08057876882F940F71466FDA772E6470239387981D3D6E13733B9C39B3BDD9B14F203BAB9CCA7278A6A56
9) Final server reply

The server verifies and confirms that auth_key_hash is unique: since it's unique, it replies with the following:

Received payload (excluding transport headers/trailers):

0000 | 00 00 00 00 00 00 00 00 01 44 45 B5 0D 07 3B 6A
0010 | 34 00 00 00 34 F7 CB 3B C0 D3 C5 02 57 C0 3F 46
0020 | A9 2F 75 67 16 9F 26 38 8D 20 B1 E5 5E 0A 10 D8
0030 | DF 35 5F C3 53 A7 06 1F 42 D9 51 C4 78 3A 0F 98
0040 | C0 6D BA F8 6A F9 B7 A0

Payload (de)serialization:

dh_gen_ok#00000004 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 014445B50D073B6A Message ID generated as specified here » (unixtime() << 32) + (N*4)
message_length 16, 4 34000000 (52 in decimal) Message body length
%(dh_gen_ok) 20, 4 34f7cb3b dh_gen_ok constructor number from TL schema
nonce 24, 16 C0D3C50257C03F46A92F7567169F2638 Value generated by client in Step 1
server_nonce 40, 16 8D20B1E55E0A10D8DF355FC353A7061F Value received from server in Step 2
new_nonce_hash1 56, 16 42D951C4783A0F98C06DBAF86AF9B7A0 The 128 lower-order bits of SHA1 of the byte string derived from the new_nonce string by adding a single byte with the value of 1, 2, or 3, and followed by another 8 bytes with auth_key_aux_hash. Different values are required to prevent an intruder from changing server response dh_gen_ok into dh_gen_retry.