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 98 E2 05 00 88 F1 E3 68
0010 | 14 00 00 00 F1 8E 7E BE 3A 13 A8 EE 6E BE 4F 9E
0020 | F0 7C F3 61 AF B3 FD 2C

Payload (de)serialization:

req_pq_multi#be7e8ef1 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 98E2050088F1E368 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 3A13A8EE6EBE4F9EF07CF361AFB3FD2C 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 28 58 33 88 F1 E3 68
0010 | 50 00 00 00 63 24 16 05 3A 13 A8 EE 6E BE 4F 9E
0020 | F0 7C F3 61 AF B3 FD 2C 86 C2 32 65 6D 7B 25 76
0030 | 57 12 B2 B2 2B 72 3B 93 08 0E B4 D6 F0 BD D2 06
0040 | 5B 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#05162463 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 0128583388F1E368 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 3A13A8EE6EBE4F9EF07CF361AFB3FD2C Value generated by client in Step 1
server_nonce 40, 16 86C232656D7B25765712B2B22B723B93 Server-generated random number
pq 56, 12 080EB4D6F0BDD2065B000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1059708141804062299
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 = 1059708141804062299

Decompose into 2 prime cofactors p < q: 1059708141804062299 = 1001313097 * 1058318467

p = 1001313097
q = 1058318467

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 0E B4 D6 F0 BD D2 06 5B 00 00 00
0010 | 04 3B AE D3 49 00 00 00 04 3F 14 A8 83 00 00 00
0020 | 3A 13 A8 EE 6E BE 4F 9E F0 7C F3 61 AF B3 FD 2C
0030 | 86 C2 32 65 6D 7B 25 76 57 12 B2 B2 2B 72 3B 93
0040 | 75 7A FC 40 72 2C 7A 9A D6 7D E9 6A 06 1A 57 D4
0050 | F2 04 45 D8 A3 E9 62 B2 C8 01 9B 17 D7 E2 78 7A
0060 | 02 00 00 00

Payload (de)serialization:

p_q_inner_data_dc#a9f55f95 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 080EB4D6F0BDD2065B000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1059708141804062299
Single-byte prefix denoting length, 8-byte string, and three bytes of padding
p 16, 8 043BAED349000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1001313097
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 24, 8 043F14A883000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1058318467
Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
nonce 32, 16 3A13A8EE6EBE4F9EF07CF361AFB3FD2C Value generated by client in Step 1
server_nonce 48, 16 86C232656D7B25765712B2B22B723B93 Value received from server in Step 2
new_nonce 64, 32 757AFC40722C7A9AD67DE96A061A57D4 F20445D8A3E962B2C8019B17D7E2787A 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 = 955FF5A9080EB4D6F0BDD2065B000000043BAED349000000043F14A8830000003A13A8EE6EBE4F9EF07CF361AFB3FD2C86C232656D7B25765712B2B22B723B93757AFC40722C7A9AD67DE96A061A57D4F20445D8A3E962B2C8019B17D7E2787A02000000
random_padding_bytes = 17598DCE68FFBFF8FA2F8A4AC759254A14BDADAA0654407CC5F2B52C416C1C4268F6C92E684A1785922053AA17E4205569C60281337895A0DEF0B92DFF54CC1E138799BCFC49F52A7F1CBDBA2689FC5B94319C867D9BE0A5F604D0FF

And this is the output:

encrypted_data = D70AD531F20021F70A0FAE144497C9D491E3021BB126A0D8C1CB0BE3D6312C93373259BC95D42E01593E80E7546A4621D3720AE2FC8E0EB84F3138CECBCE3CB64E060E4FFF44A574BD24B8A09AC1C7FF3E8EFCE2D5F0E17E1915B87018B9711D0873C9C59D65C57E0EBD6DF542D9A22200ED3B001D2C21B01B0E3ABCF0E0640C6B5CAC4CAC42522DC047F635C64B48CCCADD9F3905351B608AF620ACFAE4CA7CF9C8EE3C1FF780A7C04D70BD96156100891E54C9E5F9264C895BDEAA3D10DE4BA5F272868EC8082DB4D36383ADF1400CFD5AA731B5FCBB0C05EF37201364446DE10D6D60A38794937C39591F8002899A6586A9E79F23A41BFC6C774064DC81E4

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 B8 F2 07 00 88 F1 E3 68
0010 | 40 01 00 00 BE E4 12 D7 3A 13 A8 EE 6E BE 4F 9E
0020 | F0 7C F3 61 AF B3 FD 2C 86 C2 32 65 6D 7B 25 76
0030 | 57 12 B2 B2 2B 72 3B 93 04 3B AE D3 49 00 00 00
0040 | 04 3F 14 A8 83 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 D7 0A D5 31 F2 00 21 F7 0A 0F AE 14
0060 | 44 97 C9 D4 91 E3 02 1B B1 26 A0 D8 C1 CB 0B E3
0070 | D6 31 2C 93 37 32 59 BC 95 D4 2E 01 59 3E 80 E7
0080 | 54 6A 46 21 D3 72 0A E2 FC 8E 0E B8 4F 31 38 CE
0090 | CB CE 3C B6 4E 06 0E 4F FF 44 A5 74 BD 24 B8 A0
00A0 | 9A C1 C7 FF 3E 8E FC E2 D5 F0 E1 7E 19 15 B8 70
00B0 | 18 B9 71 1D 08 73 C9 C5 9D 65 C5 7E 0E BD 6D F5
00C0 | 42 D9 A2 22 00 ED 3B 00 1D 2C 21 B0 1B 0E 3A BC
00D0 | F0 E0 64 0C 6B 5C AC 4C AC 42 52 2D C0 47 F6 35
00E0 | C6 4B 48 CC CA DD 9F 39 05 35 1B 60 8A F6 20 AC
00F0 | FA E4 CA 7C F9 C8 EE 3C 1F F7 80 A7 C0 4D 70 BD
0100 | 96 15 61 00 89 1E 54 C9 E5 F9 26 4C 89 5B DE AA
0110 | 3D 10 DE 4B A5 F2 72 86 8E C8 08 2D B4 D3 63 83
0120 | AD F1 40 0C FD 5A A7 31 B5 FC BB 0C 05 EF 37 20
0130 | 13 64 44 6D E1 0D 6D 60 A3 87 94 93 7C 39 59 1F
0140 | 80 02 89 9A 65 86 A9 E7 9F 23 A4 1B FC 6C 77 40
0150 | 64 DC 81 E4

Payload (de)serialization:

req_DH_params#d712e4be 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 B8F2070088F1E368 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 3A13A8EE6EBE4F9EF07CF361AFB3FD2C Value generated by client in Step 1
server_nonce 40, 16 86C232656D7B25765712B2B22B723B93 Value received from server in Step 2
p 56, 8 043BAED349000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1001313097
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 64, 8 043F14A883000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1058318467
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 FE000100D70AD531F20021F70A0FAE14 4497C9D491E3021BB126A0D8C1CB0BE3 D6312C93373259BC95D42E01593E80E7 546A4621D3720AE2FC8E0EB84F3138CE CBCE3CB64E060E4FFF44A574BD24B8A0 9AC1C7FF3E8EFCE2D5F0E17E1915B870 18B9711D0873C9C59D65C57E0EBD6DF5 42D9A22200ED3B001D2C21B01B0E3ABC F0E0640C6B5CAC4CAC42522DC047F635 C64B48CCCADD9F3905351B608AF620AC FAE4CA7CF9C8EE3C1FF780A7C04D70BD 96156100891E54C9E5F9264C895BDEAA 3D10DE4BA5F272868EC8082DB4D36383 ADF1400CFD5AA731B5FCBB0C05EF3720 1364446DE10D6D60A38794937C39591F 8002899A6586A9E79F23A41BFC6C7740
64DC81E4
Value generated above
6) Server responds with:

Received payload (excluding transport headers/trailers):

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

Payload (de)serialization:

server_DH_params_ok#d0e8075c 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 01604A5D88F1E368 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 3A13A8EE6EBE4F9EF07CF361AFB3FD2C Value generated by client in Step 1
server_nonce 40, 16 86C232656D7B25765712B2B22B723B93 Value received from server in Step 2
encrypted_answer 56, 596 FE5002009D26D1066F664718AF67FF4F 4E9D7819CD440504B178C0B55DEEF467 8B886C1F1549BA6866538C4FBEAE88B3 D2B8AC9F14239C23F87107AE5C142C63 48048C49B3C4DF3B88643FE03BBF938A C0B90A7800FC9B3961C3A1B3BC991E3E 90C2DB521908577B8235FDED83069D60 8E4CB0DE9135F27E4FF2A71DD68CEB4D D25DD23AE9EBB685A383925B0947C328 53371E41C02E06CEDCEDADB773B30528 49997C27D5432948545901F7A06F4D02 026A7039E7DA96535A85616DA14E1707 44953D78480AD4F8119F9E7BD6DC19C4 DDD41770F1D128A33A04AF4F1FCA00E9 2B15A1D3B6B0CAC50D84ED8CB10B91A9 305DFDB60940606858797E451A486952 88F5B2B3FC3CB7C93306BC901F471B68 BF44205F4DA740D168D237679B07EAFD 2FA116E525012415C0BD7F274402F3FB 2DA845A4FDB65904060661BE6DF2993E 5B6EB3A387992A1B4DDCC664C721D002 543362B862E48B8B5CB1E10E096EC34F 141D72554756C42F93DA8ABC93840975 CC8D0D7295D7EB8114AA556266C2DA2D 510F065010547501D654A678BA724380 A7C0763E49758543AB66157AC2FE5999 7F578204DE04C1620E439D089628EA4A DF847E53FD36EFE826192A936391A0EB 0973A0D52B4455AAC7A851515D306EC7 92C45CB6497804F23185A9A63590DA95 E0A227A436CE501891E53CDE0FFB4CA0 265B0038DBC7165AEF9BAE7F79E0B057 DD9C811C6C88C09D0CA1AAF3E1F7623A 293B4E0AA7E901CD7432CB58D0CB4FE8 BAE7AA0EA04B54F16BC35F480EC87DDB 50C1BC17BE192B584C315EDFC8AED49B F6B77C7F22FE19C283EB4859E7DEFBB1
EDF0C8DE
See below

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

encrypted_answer = 9D26D1066F664718AF67FF4F4E9D7819CD440504B178C0B55DEEF4678B886C1F1549BA6866538C4FBEAE88B3D2B8AC9F14239C23F87107AE5C142C6348048C49B3C4DF3B88643FE03BBF938AC0B90A7800FC9B3961C3A1B3BC991E3E90C2DB521908577B8235FDED83069D608E4CB0DE9135F27E4FF2A71DD68CEB4DD25DD23AE9EBB685A383925B0947C32853371E41C02E06CEDCEDADB773B3052849997C27D5432948545901F7A06F4D02026A7039E7DA96535A85616DA14E170744953D78480AD4F8119F9E7BD6DC19C4DDD41770F1D128A33A04AF4F1FCA00E92B15A1D3B6B0CAC50D84ED8CB10B91A9305DFDB60940606858797E451A48695288F5B2B3FC3CB7C93306BC901F471B68BF44205F4DA740D168D237679B07EAFD2FA116E525012415C0BD7F274402F3FB2DA845A4FDB65904060661BE6DF2993E5B6EB3A387992A1B4DDCC664C721D002543362B862E48B8B5CB1E10E096EC34F141D72554756C42F93DA8ABC93840975CC8D0D7295D7EB8114AA556266C2DA2D510F065010547501D654A678BA724380A7C0763E49758543AB66157AC2FE59997F578204DE04C1620E439D089628EA4ADF847E53FD36EFE826192A936391A0EB0973A0D52B4455AAC7A851515D306EC792C45CB6497804F23185A9A63590DA95E0A227A436CE501891E53CDE0FFB4CA0265B0038DBC7165AEF9BAE7F79E0B057DD9C811C6C88C09D0CA1AAF3E1F7623A293B4E0AA7E901CD7432CB58D0CB4FE8BAE7AA0EA04B54F16BC35F480EC87DDB50C1BC17BE192B584C315EDFC8AED49BF6B77C7F22FE19C283EB4859E7DEFBB1EDF0C8DE
tmp_aes_key = 1065483DD1C36EBB5EF44265FB0FC603F91E28BAE235A56503EC0248FCADC3E7
tmp_aes_iv = D24B38F7A5D537A06C54585001B736924EB43C8DE386956D28FFA6DA757AFC40

Yielding:

answer_with_hash = EAD623026459A918235A5C54FCF3880D39D4027ABA0D89B53A13A8EE6EBE4F9EF07CF361AFB3FD2C86C232656D7B25765712B2B22B723B9303000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001000C26BF3B1A2CA558F962D69E7C9B710F52C3822ACFA384A9EE8A50FA35270BDC39A690F5EFB9AA3B46685A5A204F381FE550C98EBFA976C5036FB00B434242C3E4A78DC0CEF5D7E0E4A27DABB0ECAC07DD31841A35A66796A3C7CD2FE64E22AC608B5FF547692431A03BE7E42D778BCD7A0C3A1D2D549C2B60B15A85A6B885EF08514596A91F24F4CD005009059A9DE1D1EE6180E0793E0D74CBA52F6106CB3C31989978B44810D1FA4227FFD1F209C11F067EAEEA602641299F9DB15C38FD4328B8AB1C4270CD249A3FA454921861B00C6859729BA9DD7407454891DBA10EC8F52B3E99723D96AA5149F7FB8ACFA25E1E9F8B1E83A85F12F2A4D737222B403A88F1E368CD93DE1D480BF345
answer = BA0D89B53A13A8EE6EBE4F9EF07CF361AFB3FD2C86C232656D7B25765712B2B22B723B9303000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001000C26BF3B1A2CA558F962D69E7C9B710F52C3822ACFA384A9EE8A50FA35270BDC39A690F5EFB9AA3B46685A5A204F381FE550C98EBFA976C5036FB00B434242C3E4A78DC0CEF5D7E0E4A27DABB0ECAC07DD31841A35A66796A3C7CD2FE64E22AC608B5FF547692431A03BE7E42D778BCD7A0C3A1D2D549C2B60B15A85A6B885EF08514596A91F24F4CD005009059A9DE1D1EE6180E0793E0D74CBA52F6106CB3C31989978B44810D1FA4227FFD1F209C11F067EAEEA602641299F9DB15C38FD4328B8AB1C4270CD249A3FA454921861B00C6859729BA9DD7407454891DBA10EC8F52B3E99723D96AA5149F7FB8ACFA25E1E9F8B1E83A85F12F2A4D737222B403A88F1E368CD93DE1D480BF345

Generated payload (excluding transport headers/trailers):

0000 | BA 0D 89 B5 3A 13 A8 EE 6E BE 4F 9E F0 7C F3 61
0010 | AF B3 FD 2C 86 C2 32 65 6D 7B 25 76 57 12 B2 B2
0020 | 2B 72 3B 93 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 | 0C 26 BF 3B 1A 2C A5 58 F9 62 D6 9E 7C 9B 71 0F
0140 | 52 C3 82 2A CF A3 84 A9 EE 8A 50 FA 35 27 0B DC
0150 | 39 A6 90 F5 EF B9 AA 3B 46 68 5A 5A 20 4F 38 1F
0160 | E5 50 C9 8E BF A9 76 C5 03 6F B0 0B 43 42 42 C3
0170 | E4 A7 8D C0 CE F5 D7 E0 E4 A2 7D AB B0 EC AC 07
0180 | DD 31 84 1A 35 A6 67 96 A3 C7 CD 2F E6 4E 22 AC
0190 | 60 8B 5F F5 47 69 24 31 A0 3B E7 E4 2D 77 8B CD
01A0 | 7A 0C 3A 1D 2D 54 9C 2B 60 B1 5A 85 A6 B8 85 EF
01B0 | 08 51 45 96 A9 1F 24 F4 CD 00 50 09 05 9A 9D E1
01C0 | D1 EE 61 80 E0 79 3E 0D 74 CB A5 2F 61 06 CB 3C
01D0 | 31 98 99 78 B4 48 10 D1 FA 42 27 FF D1 F2 09 C1
01E0 | 1F 06 7E AE EA 60 26 41 29 9F 9D B1 5C 38 FD 43
01F0 | 28 B8 AB 1C 42 70 CD 24 9A 3F A4 54 92 18 61 B0
0200 | 0C 68 59 72 9B A9 DD 74 07 45 48 91 DB A1 0E C8
0210 | F5 2B 3E 99 72 3D 96 AA 51 49 F7 FB 8A CF A2 5E
0220 | 1E 9F 8B 1E 83 A8 5F 12 F2 A4 D7 37 22 2B 40 3A
0230 | 88 F1 E3 68

Payload (de)serialization:

server_DH_inner_data#b5890dba 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 3A13A8EE6EBE4F9EF07CF361AFB3FD2C Value generated by client in Step 1
server_nonce 20, 16 86C232656D7B25765712B2B22B723B93 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 FE0001000C26BF3B1A2CA558F962D69E 7C9B710F52C3822ACFA384A9EE8A50FA 35270BDC39A690F5EFB9AA3B46685A5A 204F381FE550C98EBFA976C5036FB00B 434242C3E4A78DC0CEF5D7E0E4A27DAB B0ECAC07DD31841A35A66796A3C7CD2F E64E22AC608B5FF547692431A03BE7E4 2D778BCD7A0C3A1D2D549C2B60B15A85 A6B885EF08514596A91F24F4CD005009 059A9DE1D1EE6180E0793E0D74CBA52F 6106CB3C31989978B44810D1FA4227FF D1F209C11F067EAEEA602641299F9DB1 5C38FD4328B8AB1C4270CD249A3FA454 921861B00C6859729BA9DD7407454891 DBA10EC8F52B3E99723D96AA5149F7FB 8ACFA25E1E9F8B1E83A85F12F2A4D737
222B403A
g_a diffie-hellman parameter
server_time 560, 4 88F1E368 (1759768968 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 = 88BA651718CDAF57A70D604ADA7D4B519B17F36223E32F6BF2639F39E3A021EB43B6528764C570834E4CA76161BD7A9E7F1880F7146F32B9031D5865A084FC2B64FED1FC78E56F39CE8DAD7D770EFA816F791FE04EFA490481C5177B914738B78A67EB5191B2559C3CA46993C60F4D72DDF28395FE2F320A5A3402E9262A9A2B54977172D9F03EA969F2DA5F65FD95FB1F0B70135DA0D411A83EE43866F8660862F5A8DA662964BFEE78BFAA45D4069C933BEAA1CF52DF2194273595F4AD70888ECCE4B7CCF3C3864B767E813CF3845FD6987DE6AAE2EE22975AD8EC5E11A48391B7919700989115D1375E9A7E24A3B6D753C6A5C99536E96D9960C205AFAB38

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

g_b = 7136CC131A2F02335872891A0E4425369906C12CA507B36102AB422394D98965E20549827DF0040A905BDBBBE7343DAD0F55D287CD672A69E2468717DC54E6D54029D0DD1F57A2A22566B6E86CF088F29723E8407DE28F022992DE5D1F659579AB3261069EEE420D23A8A27D85F5EE09F90DF97AB2EADAB1F686D170F719A50966E1854A015173036F10B6FB75E884DE4E58198C4B0E3389002F5E7FA8073206C0D062BDF706C612BD753F2E874E6072E480A4FB7A1E76B70153990E2C94E611A9EA81DC803E3C61AC6EC0EBD9DA1F609CE681C8E5D7CD00BC9F18B363D9374A7E03E8125E51352E2D68296EFADB831EC8C1F2B33A19573674923B3587630241
7.1) generation of encrypted_data

Generated payload (excluding transport headers/trailers):

0000 | 54 B6 43 66 3A 13 A8 EE 6E BE 4F 9E F0 7C F3 61
0010 | AF B3 FD 2C 86 C2 32 65 6D 7B 25 76 57 12 B2 B2
0020 | 2B 72 3B 93 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | 71 36 CC 13 1A 2F 02 33 58 72 89 1A 0E 44 25 36
0040 | 99 06 C1 2C A5 07 B3 61 02 AB 42 23 94 D9 89 65
0050 | E2 05 49 82 7D F0 04 0A 90 5B DB BB E7 34 3D AD
0060 | 0F 55 D2 87 CD 67 2A 69 E2 46 87 17 DC 54 E6 D5
0070 | 40 29 D0 DD 1F 57 A2 A2 25 66 B6 E8 6C F0 88 F2
0080 | 97 23 E8 40 7D E2 8F 02 29 92 DE 5D 1F 65 95 79
0090 | AB 32 61 06 9E EE 42 0D 23 A8 A2 7D 85 F5 EE 09
00A0 | F9 0D F9 7A B2 EA DA B1 F6 86 D1 70 F7 19 A5 09
00B0 | 66 E1 85 4A 01 51 73 03 6F 10 B6 FB 75 E8 84 DE
00C0 | 4E 58 19 8C 4B 0E 33 89 00 2F 5E 7F A8 07 32 06
00D0 | C0 D0 62 BD F7 06 C6 12 BD 75 3F 2E 87 4E 60 72
00E0 | E4 80 A4 FB 7A 1E 76 B7 01 53 99 0E 2C 94 E6 11
00F0 | A9 EA 81 DC 80 3E 3C 61 AC 6E C0 EB D9 DA 1F 60
0100 | 9C E6 81 C8 E5 D7 CD 00 BC 9F 18 B3 63 D9 37 4A
0110 | 7E 03 E8 12 5E 51 35 2E 2D 68 29 6E FA DB 83 1E
0120 | C8 C1 F2 B3 3A 19 57 36 74 92 3B 35 87 63 02 41

Payload (de)serialization:

client_DH_inner_data#6643b654 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 3A13A8EE6EBE4F9EF07CF361AFB3FD2C Value generated by client in Step 1
server_nonce 20, 16 86C232656D7B25765712B2B22B723B93 Value received from server in Step 2
g_b 36, 260 FE0001007136CC131A2F02335872891A 0E4425369906C12CA507B36102AB4223 94D98965E20549827DF0040A905BDBBB E7343DAD0F55D287CD672A69E2468717 DC54E6D54029D0DD1F57A2A22566B6E8 6CF088F29723E8407DE28F022992DE5D 1F659579AB3261069EEE420D23A8A27D 85F5EE09F90DF97AB2EADAB1F686D170 F719A50966E1854A015173036F10B6FB 75E884DE4E58198C4B0E3389002F5E7F A8073206C0D062BDF706C612BD753F2E 874E6072E480A4FB7A1E76B70153990E 2C94E611A9EA81DC803E3C61AC6EC0EB D9DA1F609CE681C8E5D7CD00BC9F18B3 63D9374A7E03E8125E51352E2D68296E FADB831EC8C1F2B33A19573674923B35
87630241
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 = 54B643663A13A8EE6EBE4F9EF07CF361AFB3FD2C86C232656D7B25765712B2B22B723B930000000000000000FE0001007136CC131A2F02335872891A0E4425369906C12CA507B36102AB422394D98965E20549827DF0040A905BDBBBE7343DAD0F55D287CD672A69E2468717DC54E6D54029D0DD1F57A2A22566B6E86CF088F29723E8407DE28F022992DE5D1F659579AB3261069EEE420D23A8A27D85F5EE09F90DF97AB2EADAB1F686D170F719A50966E1854A015173036F10B6FB75E884DE4E58198C4B0E3389002F5E7FA8073206C0D062BDF706C612BD753F2E874E6072E480A4FB7A1E76B70153990E2C94E611A9EA81DC803E3C61AC6EC0EBD9DA1F609CE681C8E5D7CD00BC9F18B363D9374A7E03E8125E51352E2D68296EFADB831EC8C1F2B33A19573674923B3587630241
padding = 2592B8F8BF1200C1C575A9CF
tmp_aes_key = 1065483DD1C36EBB5EF44265FB0FC603F91E28BAE235A56503EC0248FCADC3E7
tmp_aes_iv = D24B38F7A5D537A06C54585001B736924EB43C8DE386956D28FFA6DA757AFC40

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 = FB061B1A5F18AEA75647409BC0A5984C215AD1CC0EAD9778BDF7D2B96A03F33590F55DEF133023A442207120991C4262D18096F41576C5A032E51502D9A286318A024082ACF61E5A32E0B1A759061FEA6DA9BC8FF209F869FB905E4FCF1DB33AA49C67EE953ABDBD2B2D711BE0FEA2F1488FBB982514DE818FA92168D3F687C3E074202262E4CE6CEC95C6D545668953234466A7603F2C8EC663E5CAB3F009DA66FC94F934553C26EEC3C5595D9306E071CE5A565D584C127541C054461B23FE625DD5AE3D0CB22DE13DC09C79E640EFDE8A6861F1FD0337BA2179EA05B9BEA8F61415F17F0B316650CF34C766A30124BA4258D5EC47CA72C53F01BBC0D92F0417D787430423AF87F5CBF10EE31901A048168999ACCBCDF18E7AD97D8CD665383BFC5192A0A4254B08DBF1868393EBA0B15E16BF2AFA07C2645948EBD990D0D940D9E2D6AF6B2FD7FE21A0869EA3BCAF

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 D4 BF 0C 00 88 F1 E3 68
0010 | 78 01 00 00 1F 5F 04 F5 3A 13 A8 EE 6E BE 4F 9E
0020 | F0 7C F3 61 AF B3 FD 2C 86 C2 32 65 6D 7B 25 76
0030 | 57 12 B2 B2 2B 72 3B 93 FE 50 01 00 FB 06 1B 1A
0040 | 5F 18 AE A7 56 47 40 9B C0 A5 98 4C 21 5A D1 CC
0050 | 0E AD 97 78 BD F7 D2 B9 6A 03 F3 35 90 F5 5D EF
0060 | 13 30 23 A4 42 20 71 20 99 1C 42 62 D1 80 96 F4
0070 | 15 76 C5 A0 32 E5 15 02 D9 A2 86 31 8A 02 40 82
0080 | AC F6 1E 5A 32 E0 B1 A7 59 06 1F EA 6D A9 BC 8F
0090 | F2 09 F8 69 FB 90 5E 4F CF 1D B3 3A A4 9C 67 EE
00A0 | 95 3A BD BD 2B 2D 71 1B E0 FE A2 F1 48 8F BB 98
00B0 | 25 14 DE 81 8F A9 21 68 D3 F6 87 C3 E0 74 20 22
00C0 | 62 E4 CE 6C EC 95 C6 D5 45 66 89 53 23 44 66 A7
00D0 | 60 3F 2C 8E C6 63 E5 CA B3 F0 09 DA 66 FC 94 F9
00E0 | 34 55 3C 26 EE C3 C5 59 5D 93 06 E0 71 CE 5A 56
00F0 | 5D 58 4C 12 75 41 C0 54 46 1B 23 FE 62 5D D5 AE
0100 | 3D 0C B2 2D E1 3D C0 9C 79 E6 40 EF DE 8A 68 61
0110 | F1 FD 03 37 BA 21 79 EA 05 B9 BE A8 F6 14 15 F1
0120 | 7F 0B 31 66 50 CF 34 C7 66 A3 01 24 BA 42 58 D5
0130 | EC 47 CA 72 C5 3F 01 BB C0 D9 2F 04 17 D7 87 43
0140 | 04 23 AF 87 F5 CB F1 0E E3 19 01 A0 48 16 89 99
0150 | AC CB CD F1 8E 7A D9 7D 8C D6 65 38 3B FC 51 92
0160 | A0 A4 25 4B 08 DB F1 86 83 93 EB A0 B1 5E 16 BF
0170 | 2A FA 07 C2 64 59 48 EB D9 90 D0 D9 40 D9 E2 D6
0180 | AF 6B 2F D7 FE 21 A0 86 9E A3 BC AF

Payload (de)serialization:

set_client_DH_params#f5045f1f 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 D4BF0C0088F1E368 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 3A13A8EE6EBE4F9EF07CF361AFB3FD2C Value generated by client in Step 1
server_nonce 40, 16 86C232656D7B25765712B2B22B723B93 Value received from server in Step 2
encrypted_data 56, 340 FE500100FB061B1A5F18AEA75647409B C0A5984C215AD1CC0EAD9778BDF7D2B9 6A03F33590F55DEF133023A442207120 991C4262D18096F41576C5A032E51502 D9A286318A024082ACF61E5A32E0B1A7 59061FEA6DA9BC8FF209F869FB905E4F CF1DB33AA49C67EE953ABDBD2B2D711B E0FEA2F1488FBB982514DE818FA92168 D3F687C3E074202262E4CE6CEC95C6D5 45668953234466A7603F2C8EC663E5CA B3F009DA66FC94F934553C26EEC3C559 5D9306E071CE5A565D584C127541C054 461B23FE625DD5AE3D0CB22DE13DC09C 79E640EFDE8A6861F1FD0337BA2179EA 05B9BEA8F61415F17F0B316650CF34C7 66A30124BA4258D5EC47CA72C53F01BB C0D92F0417D787430423AF87F5CBF10E E31901A048168999ACCBCDF18E7AD97D 8CD665383BFC5192A0A4254B08DBF186 8393EBA0B15E16BF2AFA07C2645948EB D990D0D940D9E2D6AF6B2FD7FE21A086
9EA3BCAF
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 = 53C4FE56A168302E279BD600FD99716F44E507571ECDC335264A211C9C8FEDA25909B1DFC4B5458640359792E5EBEACF9DE6021B9F54915CD7E051E57454FF4DBFFE59EA6CF9AB10A3AF6C8859BFD11A60F2C53E2FC45F7CE5C004693A91B12AD77A7F113EBC77439DF0BD35967E7B7C763E2404A70028FBCB0A06A90E9C00225DF693AF2C5B8C3D372618DCF01AAC40EA389417AF0A9B13F2C5A39C2EBF3FC9C375FA408E59E24C18DFC7F9A4AC648BCE22E1905A00AF74FB5651EE343F2237798A5473FA7DE3050D40FB3F4A8A4555B71005C6081CB3CC42AC3B936B4871715CF0FA41FDB64D9CE2C869E46307E89B9CD0B7704CA86D29AAC117DD479D96F4
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 88 67 18 8A F1 E3 68
0010 | 34 00 00 00 34 F7 CB 3B 3A 13 A8 EE 6E BE 4F 9E
0020 | F0 7C F3 61 AF B3 FD 2C 86 C2 32 65 6D 7B 25 76
0030 | 57 12 B2 B2 2B 72 3B 93 FE BD D6 53 90 1D 53 B6
0040 | 67 60 89 96 81 29 1D AC

Payload (de)serialization:

dh_gen_ok#3bcbf734 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 018867188AF1E368 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 3A13A8EE6EBE4F9EF07CF361AFB3FD2C Value generated by client in Step 1
server_nonce 40, 16 86C232656D7B25765712B2B22B723B93 Value received from server in Step 2
new_nonce_hash1 56, 16 FEBDD653901D53B66760899681291DAC 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.