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 84 8C 00 00 B1 AF 9C 64
0010 | 14 00 00 00 F1 8E 7E BE B0 BB 83 C2 68 49 38 B7
0020 | 6A C4 92 3A A5 45 C8 F0

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 848C0000B1AF9C64 Message ID generated as specified here »
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 B0BB83C2684938B76AC4923AA545C8F0 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 9C 04 77 B1 AF 9C 64
0010 | 50 00 00 00 63 24 16 05 B0 BB 83 C2 68 49 38 B7
0020 | 6A C4 92 3A A5 45 C8 F0 59 2E 37 C5 BF 99 B8 DD
0030 | AE 33 E6 EE 39 4B 47 42 08 2E 07 1E 8F 6E F5 45
0040 | 63 00 00 00 15 C4 B5 1C 03 00 00 00 A5 B7 F7 09
0050 | 35 5F C3 0B 21 6B E8 6C 02 2B B4 C3 85 FD 64 DE
0060 | 85 1D 9D D0

Payload (de)serialization:

resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector<long> = 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 019C0477B1AF9C64 Message ID generated as specified here »
message_length 16, 4 50000000 (80 in decimal) Message body length
%(resPQ) 20, 4 63241605 resPQ constructor number from TL schema
nonce 24, 16 B0BB83C2684938B76AC4923AA545C8F0 Value generated by client in Step 1
server_nonce 40, 16 592E37C5BF99B8DDAE33E6EE394B4742 Server-generated random number
pq 56, 12 082E071E8F6EF54563000000
TL byte deserialization
=> bigendian conversion to decimal
=> 3316653251972384099
Single-byte prefix denoting length, an 8-byte string, and three bytes of padding
%(Vector long) 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 A5B7F709355FC30B 64 lower-order bits of SHA1(server_public_key)
server_public_key_fingerprints[1] 84, 8 216BE86C022BB4C3 64 lower-order bits of SHA1(server_public_key)
server_public_key_fingerprints[2] 92, 8 85FD64DE851D9DD0 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 = 3316653251972384099

Decompose into 2 prime cofactors: 3316653251972384099 = 1704206131 * 1946157329

p = 1704206131
q = 1946157329

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 2E 07 1E 8F 6E F5 45 63 00 00 00
0010 | 04 65 94 1F 33 00 00 00 04 74 00 01 11 00 00 00
0020 | B0 BB 83 C2 68 49 38 B7 6A C4 92 3A A5 45 C8 F0
0030 | 59 2E 37 C5 BF 99 B8 DD AE 33 E6 EE 39 4B 47 42
0040 | FA 05 D4 1E 4C C4 D7 94 58 F8 26 B2 33 4B 26 67
0050 | 5C C6 64 8E 23 E7 62 6B 75 A1 B9 09 98 1A C9 55
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 082E071E8F6EF54563000000
TL byte deserialization
=> bigendian conversion to decimal
=> 3316653251972384099
Single-byte prefix denoting length, 8-byte string, and three bytes of padding
p 16, 8 0465941F33000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1704206131
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 24, 8 0474000111000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1946157329
Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
nonce 32, 16 B0BB83C2684938B76AC4923AA545C8F0 Value generated by client in Step 1
server_nonce 48, 16 592E37C5BF99B8DDAE33E6EE394B4742 Value received from server in Step 2
new_nonce 64, 32 FA05D41E4CC4D79458F826B2334B2667 5CC6648E23E7626B75A1B909981AC955 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 = 955FF5A9082E071E8F6EF545630000000465941F330000000474000111000000B0BB83C2684938B76AC4923AA545C8F0592E37C5BF99B8DDAE33E6EE394B4742FA05D41E4CC4D79458F826B2334B26675CC6648E23E7626B75A1B909981AC95502000000
random_padding_bytes = 2F9E22AC78033569C4B3F7035D5FFAFC3EBF28ECD70A65926B2E64D9118B8AB14EB6A100AA469AACCB3B9961D5E588C19A4E0C17F8C5CEDC003442FD0AECC129BFD6EEA4AD293FF753A0B194AB005F24E74FA78A98E10EAA2F16AD98

And this is the output:

encrypted_data = DF92287F32BBAE22049A7DF88007F9FBE0103D8DF533E4ED59C0A25B6D99FA0A9F2C83A8E45C28B2C7AB6D541B38C6254FDE09B773B38ECDB94B660D71415CDFD4B8BAD8B91DC60B837BF4205A781AB77885D8E0EF71E329D4B9356302C4D2BE16E34A6A939559BE65EC2F0EFE2CD561E9B058A13B5C8EEEB6907DF897AA7E48BE7F7DE1D13058476C8EDF60A79330D0A9178E3FA064EF069063BC37AAA3CC1B5E0E347290E5C1197A10C01986035E20C0B106074C857906131ACE5F75900037E16F66FC0D0D62383412CE7D7A9DCC45AFC3025AD9976268664F4162581175139A2F0910C69CDFBE9DA93CAC8C3CA67A4278E2CD2A67EF9D9FF5D7F866E24596

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 74 07 01 00 B1 AF 9C 64
0010 | 40 01 00 00 BE E4 12 D7 B0 BB 83 C2 68 49 38 B7
0020 | 6A C4 92 3A A5 45 C8 F0 59 2E 37 C5 BF 99 B8 DD
0030 | AE 33 E6 EE 39 4B 47 42 04 65 94 1F 33 00 00 00
0040 | 04 74 00 01 11 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 DF 92 28 7F 32 BB AE 22 04 9A 7D F8
0060 | 80 07 F9 FB E0 10 3D 8D F5 33 E4 ED 59 C0 A2 5B
0070 | 6D 99 FA 0A 9F 2C 83 A8 E4 5C 28 B2 C7 AB 6D 54
0080 | 1B 38 C6 25 4F DE 09 B7 73 B3 8E CD B9 4B 66 0D
0090 | 71 41 5C DF D4 B8 BA D8 B9 1D C6 0B 83 7B F4 20
00A0 | 5A 78 1A B7 78 85 D8 E0 EF 71 E3 29 D4 B9 35 63
00B0 | 02 C4 D2 BE 16 E3 4A 6A 93 95 59 BE 65 EC 2F 0E
00C0 | FE 2C D5 61 E9 B0 58 A1 3B 5C 8E EE B6 90 7D F8
00D0 | 97 AA 7E 48 BE 7F 7D E1 D1 30 58 47 6C 8E DF 60
00E0 | A7 93 30 D0 A9 17 8E 3F A0 64 EF 06 90 63 BC 37
00F0 | AA A3 CC 1B 5E 0E 34 72 90 E5 C1 19 7A 10 C0 19
0100 | 86 03 5E 20 C0 B1 06 07 4C 85 79 06 13 1A CE 5F
0110 | 75 90 00 37 E1 6F 66 FC 0D 0D 62 38 34 12 CE 7D
0120 | 7A 9D CC 45 AF C3 02 5A D9 97 62 68 66 4F 41 62
0130 | 58 11 75 13 9A 2F 09 10 C6 9C DF BE 9D A9 3C AC
0140 | 8C 3C A6 7A 42 78 E2 CD 2A 67 EF 9D 9F F5 D7 F8
0150 | 66 E2 45 96

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 74070100B1AF9C64 Message ID generated as specified here »
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 B0BB83C2684938B76AC4923AA545C8F0 Value generated by client in Step 1
server_nonce 40, 16 592E37C5BF99B8DDAE33E6EE394B4742 Value received from server in Step 2
p 56, 8 0465941F33000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1704206131
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 64, 8 0474000111000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1946157329
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 FE000100DF92287F32BBAE22049A7DF8 8007F9FBE0103D8DF533E4ED59C0A25B 6D99FA0A9F2C83A8E45C28B2C7AB6D54 1B38C6254FDE09B773B38ECDB94B660D 71415CDFD4B8BAD8B91DC60B837BF420 5A781AB77885D8E0EF71E329D4B93563 02C4D2BE16E34A6A939559BE65EC2F0E FE2CD561E9B058A13B5C8EEEB6907DF8 97AA7E48BE7F7DE1D13058476C8EDF60 A79330D0A9178E3FA064EF069063BC37 AAA3CC1B5E0E347290E5C1197A10C019 86035E20C0B106074C857906131ACE5F 75900037E16F66FC0D0D62383412CE7D 7A9DCC45AFC3025AD9976268664F4162 581175139A2F0910C69CDFBE9DA93CAC 8C3CA67A4278E2CD2A67EF9D9FF5D7F8
66E24596
Value generated above
6) Server responds with:

Received payload (excluding transport headers/trailers):

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

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 0130871EB2AF9C64 Message ID generated as specified here »
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 B0BB83C2684938B76AC4923AA545C8F0 Value generated by client in Step 1
server_nonce 40, 16 592E37C5BF99B8DDAE33E6EE394B4742 Value received from server in Step 2
encrypted_answer 56, 596 FE500200073FF0CEBA1A9EF880F885E4 D0E9C1EF93F61A18BD1BB78D7A36D3BF 1B766E28139102C485BA0D47D383C8E6 039DBBD378BAA64DC067F1604396DAA0 4D721E110D2308F495A534DE443006DE 9176B4B8D927248402E16D69FC8F7348 54BAFBF806004E43269CA8C87291D4F8 F436843A0CB3FD631FE4D7F41E8FAC2E 34EF840BDAC03314248A4AF691ADAB7A 0C6BDCCA3D85FD49E49AE6E518AF6DDA 95CF034F90EB1B4250CDF603F58121BC 3C4889E0C6730C89773A8D77C9FC7AF3 05C9F93BD83510FBF1B98ED70849615A D2C9497F9C8A944CB1D3A51AD10144B7 777A4A5ED959FFE03B873D4CF010B361 C62F7B423EEC02CACE0D280A6E341EA5 BDAE28EFBA69D050581056356B7B6F66 D9A9514416578842240BED8633381F0C 4AB006C54B6029E58EAFA36F872EE7C9 5B5DF591C7C2686A3E61489FFB06F910 AC03C5F456B9A3C34A5CCACE676E875C F3E76791C4AD88C31F9D6F43EF4E9EF4 8E0DBC301EF29D2EB38030705E1A0F25 F2007D5412966638DC5114371A63082C 81462C3B700EA5356E28923F5087AF05 1CFD8159B64B2ADC804E66CB70F6AD25 1721C6B8CA2F2168731432C967BC8BAE AD029640E80C2DC27AE03CFC5FC11739 65F9CDF8C2931B6EC5D46351D7E79D33 AFBE6C58663F3EADA5B2A49DF6CDE1C9 90786108116511DD9FC673E0559D84A5 5136C001830FE62C495C90398E960549 4E24107C0267BDA129797B7B1ACF861C 04F07D6BBA8B111F888611E5631EFF97 16C406A7AE8BE2DDE1D873FB571C8208 8ABD18FE051F6E4AEE9B9094C63FAC38 CA68B4EA46F12CD709DFDAC944ED46AF
792FDBA2
See below

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

encrypted_answer = 073FF0CEBA1A9EF880F885E4D0E9C1EF93F61A18BD1BB78D7A36D3BF1B766E28139102C485BA0D47D383C8E6039DBBD378BAA64DC067F1604396DAA04D721E110D2308F495A534DE443006DE9176B4B8D927248402E16D69FC8F734854BAFBF806004E43269CA8C87291D4F8F436843A0CB3FD631FE4D7F41E8FAC2E34EF840BDAC03314248A4AF691ADAB7A0C6BDCCA3D85FD49E49AE6E518AF6DDA95CF034F90EB1B4250CDF603F58121BC3C4889E0C6730C89773A8D77C9FC7AF305C9F93BD83510FBF1B98ED70849615AD2C9497F9C8A944CB1D3A51AD10144B7777A4A5ED959FFE03B873D4CF010B361C62F7B423EEC02CACE0D280A6E341EA5BDAE28EFBA69D050581056356B7B6F66D9A9514416578842240BED8633381F0C4AB006C54B6029E58EAFA36F872EE7C95B5DF591C7C2686A3E61489FFB06F910AC03C5F456B9A3C34A5CCACE676E875CF3E76791C4AD88C31F9D6F43EF4E9EF48E0DBC301EF29D2EB38030705E1A0F25F2007D5412966638DC5114371A63082C81462C3B700EA5356E28923F5087AF051CFD8159B64B2ADC804E66CB70F6AD251721C6B8CA2F2168731432C967BC8BAEAD029640E80C2DC27AE03CFC5FC1173965F9CDF8C2931B6EC5D46351D7E79D33AFBE6C58663F3EADA5B2A49DF6CDE1C990786108116511DD9FC673E0559D84A55136C001830FE62C495C90398E9605494E24107C0267BDA129797B7B1ACF861C04F07D6BBA8B111F888611E5631EFF9716C406A7AE8BE2DDE1D873FB571C82088ABD18FE051F6E4AEE9B9094C63FAC38CA68B4EA46F12CD709DFDAC944ED46AF792FDBA2
tmp_aes_key = 3826079A7BBD2CC9B9AE0E9D1BEEDA1A663CE630DC446D259DE256A1C953E8FA
tmp_aes_iv = 7A6748BA29AAC95EF75BD4588351617832FD34568EF1C4018F04F871FA05D41E

Yielding:

answer_with_hash = 3C9D681E6DB06E8B9F3D3CA74BC92D7E67D227D0BA0D89B5B0BB83C2684938B76AC4923AA545C8F0592E37C5BF99B8DDAE33E6EE394B474203000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001002FDAB5904B04F687AFF2E819845CF3BE57A147004CFFEF1C5DEA2574EB87C7A1462EAF356CBAD7B11BC1AAF4C64924555834B4E0FECB94118F21958824D8E0EB78FD33BA711806508E1EFA3BDB4520DBD4459CA6BAD3A8CD59874AE8295DBD0B6EC31C2A381406FCFBCA4031EDB433CDCF43551BEDAC54CBF8209542C22BC0D564FC8585945869AF496994DEE5E9B1E59C96020713B4B3AE90ED7DC68FD1DB5B81C2411E7C0E70893BC1A5804563D424AE95A453419AFFEB3B8A8AF7C9995041DDBB3117F105397B250C2FF1F565926000CC06E175B9A7078ABFA6383D0771822291D83BC82DCD16E991B4ACF7F9C17814F6715D3517F4E66401863418F16AABB2AF9C641C1005E08D6EEDB1
answer = BA0D89B5B0BB83C2684938B76AC4923AA545C8F0592E37C5BF99B8DDAE33E6EE394B474203000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001002FDAB5904B04F687AFF2E819845CF3BE57A147004CFFEF1C5DEA2574EB87C7A1462EAF356CBAD7B11BC1AAF4C64924555834B4E0FECB94118F21958824D8E0EB78FD33BA711806508E1EFA3BDB4520DBD4459CA6BAD3A8CD59874AE8295DBD0B6EC31C2A381406FCFBCA4031EDB433CDCF43551BEDAC54CBF8209542C22BC0D564FC8585945869AF496994DEE5E9B1E59C96020713B4B3AE90ED7DC68FD1DB5B81C2411E7C0E70893BC1A5804563D424AE95A453419AFFEB3B8A8AF7C9995041DDBB3117F105397B250C2FF1F565926000CC06E175B9A7078ABFA6383D0771822291D83BC82DCD16E991B4ACF7F9C17814F6715D3517F4E66401863418F16AABB2AF9C641C1005E08D6EEDB1

Generated payload (excluding transport headers/trailers):

0000 | BA 0D 89 B5 B0 BB 83 C2 68 49 38 B7 6A C4 92 3A
0010 | A5 45 C8 F0 59 2E 37 C5 BF 99 B8 DD AE 33 E6 EE
0020 | 39 4B 47 42 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 | 2F DA B5 90 4B 04 F6 87 AF F2 E8 19 84 5C F3 BE
0140 | 57 A1 47 00 4C FF EF 1C 5D EA 25 74 EB 87 C7 A1
0150 | 46 2E AF 35 6C BA D7 B1 1B C1 AA F4 C6 49 24 55
0160 | 58 34 B4 E0 FE CB 94 11 8F 21 95 88 24 D8 E0 EB
0170 | 78 FD 33 BA 71 18 06 50 8E 1E FA 3B DB 45 20 DB
0180 | D4 45 9C A6 BA D3 A8 CD 59 87 4A E8 29 5D BD 0B
0190 | 6E C3 1C 2A 38 14 06 FC FB CA 40 31 ED B4 33 CD
01A0 | CF 43 55 1B ED AC 54 CB F8 20 95 42 C2 2B C0 D5
01B0 | 64 FC 85 85 94 58 69 AF 49 69 94 DE E5 E9 B1 E5
01C0 | 9C 96 02 07 13 B4 B3 AE 90 ED 7D C6 8F D1 DB 5B
01D0 | 81 C2 41 1E 7C 0E 70 89 3B C1 A5 80 45 63 D4 24
01E0 | AE 95 A4 53 41 9A FF EB 3B 8A 8A F7 C9 99 50 41
01F0 | DD BB 31 17 F1 05 39 7B 25 0C 2F F1 F5 65 92 60
0200 | 00 CC 06 E1 75 B9 A7 07 8A BF A6 38 3D 07 71 82
0210 | 22 91 D8 3B C8 2D CD 16 E9 91 B4 AC F7 F9 C1 78
0220 | 14 F6 71 5D 35 17 F4 E6 64 01 86 34 18 F1 6A AB
0230 | B2 AF 9C 64

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 B0BB83C2684938B76AC4923AA545C8F0 Value generated by client in Step 1
server_nonce 20, 16 592E37C5BF99B8DDAE33E6EE394B4742 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 FE0001002FDAB5904B04F687AFF2E819 845CF3BE57A147004CFFEF1C5DEA2574 EB87C7A1462EAF356CBAD7B11BC1AAF4 C64924555834B4E0FECB94118F219588 24D8E0EB78FD33BA711806508E1EFA3B DB4520DBD4459CA6BAD3A8CD59874AE8 295DBD0B6EC31C2A381406FCFBCA4031 EDB433CDCF43551BEDAC54CBF8209542 C22BC0D564FC8585945869AF496994DE E5E9B1E59C96020713B4B3AE90ED7DC6 8FD1DB5B81C2411E7C0E70893BC1A580 4563D424AE95A453419AFFEB3B8A8AF7 C9995041DDBB3117F105397B250C2FF1 F565926000CC06E175B9A7078ABFA638 3D0771822291D83BC82DCD16E991B4AC F7F9C17814F6715D3517F4E664018634
18F16AAB
g_a diffie-hellman parameter
server_time 560, 4 B2AF9C64 (1687990194 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 = 29F2FD3102D844146B82E7C115C554A80961BC260BCA739BB670787AF0A72A512BA2E47AD58D0C478415251E4D0F7A737C2BF06A364C6E995ED596C88F4685F412B60205ECB9FA3ECA18A5B7B2DBEF3F26614806067E2F5831BB9CFF38278A25BB79A8F081A9E72E92CF74DE524DFBC07B6F5F77DF5F1EFF385E0B943282DF43A220AF62387F662982CCEDB59302EAD733438089FE871856F3C6E9221198094EA76E20868AEC4A7D7C809223CB28627DF3A05961B5148BE043CC64ECA1BFCC427F476E8A6769CDD7F5B774311BC166DB8FEC80E7C2BB9DF3B391D5D441B6BB35F0828BB9A22C9151FC63F1F3C04517C127A0BB98A2850867D7074E8D0C2FC576

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

g_b = 69A19DF1CA7E2F7EB2D1C4FB9BA2856EF2AA19510669FF991757F7A3A10AA176A81CBD993DC7BD794C4E169056601BABFFE5C1A8DC6BCB705BB24BDB5E17280D26DAF0A9A801558CB87A11E30D6E8DD29CC039D014EA819CD0F8148CBA1BDB21331FFCB6063ED8FB66A6E90A02A80B68CDE53CB45D1266E8C19617FDD5AFD824001FD16BF666A1946B54B45C751CDD535B3718C6BE7A2EBAD4B35F5CA61D128B5B10ED4223C08D7294FCE18C8D30B5CFC8D73A80469150F7180F5F76F4FEAA0156EFA7665BB37F87B5F9EEAA654550555C05F91342608BB76F1E394EA6C51CE64589540E8729F9F5AE1B33108E8D35233ABFEE824AA2B940C5F04335CA59E0C4
7.1) generation of encrypted_data

Generated payload (excluding transport headers/trailers):

0000 | 54 B6 43 66 B0 BB 83 C2 68 49 38 B7 6A C4 92 3A
0010 | A5 45 C8 F0 59 2E 37 C5 BF 99 B8 DD AE 33 E6 EE
0020 | 39 4B 47 42 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | 69 A1 9D F1 CA 7E 2F 7E B2 D1 C4 FB 9B A2 85 6E
0040 | F2 AA 19 51 06 69 FF 99 17 57 F7 A3 A1 0A A1 76
0050 | A8 1C BD 99 3D C7 BD 79 4C 4E 16 90 56 60 1B AB
0060 | FF E5 C1 A8 DC 6B CB 70 5B B2 4B DB 5E 17 28 0D
0070 | 26 DA F0 A9 A8 01 55 8C B8 7A 11 E3 0D 6E 8D D2
0080 | 9C C0 39 D0 14 EA 81 9C D0 F8 14 8C BA 1B DB 21
0090 | 33 1F FC B6 06 3E D8 FB 66 A6 E9 0A 02 A8 0B 68
00A0 | CD E5 3C B4 5D 12 66 E8 C1 96 17 FD D5 AF D8 24
00B0 | 00 1F D1 6B F6 66 A1 94 6B 54 B4 5C 75 1C DD 53
00C0 | 5B 37 18 C6 BE 7A 2E BA D4 B3 5F 5C A6 1D 12 8B
00D0 | 5B 10 ED 42 23 C0 8D 72 94 FC E1 8C 8D 30 B5 CF
00E0 | C8 D7 3A 80 46 91 50 F7 18 0F 5F 76 F4 FE AA 01
00F0 | 56 EF A7 66 5B B3 7F 87 B5 F9 EE AA 65 45 50 55
0100 | 5C 05 F9 13 42 60 8B B7 6F 1E 39 4E A6 C5 1C E6
0110 | 45 89 54 0E 87 29 F9 F5 AE 1B 33 10 8E 8D 35 23
0120 | 3A BF EE 82 4A A2 B9 40 C5 F0 43 35 CA 59 E0 C4

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 B0BB83C2684938B76AC4923AA545C8F0 Value generated by client in Step 1
server_nonce 20, 16 592E37C5BF99B8DDAE33E6EE394B4742 Value received from server in Step 2
g_b 36, 260 FE00010069A19DF1CA7E2F7EB2D1C4FB 9BA2856EF2AA19510669FF991757F7A3 A10AA176A81CBD993DC7BD794C4E1690 56601BABFFE5C1A8DC6BCB705BB24BDB 5E17280D26DAF0A9A801558CB87A11E3 0D6E8DD29CC039D014EA819CD0F8148C BA1BDB21331FFCB6063ED8FB66A6E90A 02A80B68CDE53CB45D1266E8C19617FD D5AFD824001FD16BF666A1946B54B45C 751CDD535B3718C6BE7A2EBAD4B35F5C A61D128B5B10ED4223C08D7294FCE18C 8D30B5CFC8D73A80469150F7180F5F76 F4FEAA0156EFA7665BB37F87B5F9EEAA 654550555C05F91342608BB76F1E394E A6C51CE64589540E8729F9F5AE1B3310 8E8D35233ABFEE824AA2B940C5F04335
CA59E0C4
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 = 54B64366B0BB83C2684938B76AC4923AA545C8F0592E37C5BF99B8DDAE33E6EE394B47420000000000000000FE00010069A19DF1CA7E2F7EB2D1C4FB9BA2856EF2AA19510669FF991757F7A3A10AA176A81CBD993DC7BD794C4E169056601BABFFE5C1A8DC6BCB705BB24BDB5E17280D26DAF0A9A801558CB87A11E30D6E8DD29CC039D014EA819CD0F8148CBA1BDB21331FFCB6063ED8FB66A6E90A02A80B68CDE53CB45D1266E8C19617FDD5AFD824001FD16BF666A1946B54B45C751CDD535B3718C6BE7A2EBAD4B35F5CA61D128B5B10ED4223C08D7294FCE18C8D30B5CFC8D73A80469150F7180F5F76F4FEAA0156EFA7665BB37F87B5F9EEAA654550555C05F91342608BB76F1E394EA6C51CE64589540E8729F9F5AE1B33108E8D35233ABFEE824AA2B940C5F04335CA59E0C4
padding = 4670CB59FFB7033A86C62AA9
tmp_aes_key = 3826079A7BBD2CC9B9AE0E9D1BEEDA1A663CE630DC446D259DE256A1C953E8FA
tmp_aes_iv = 7A6748BA29AAC95EF75BD4588351617832FD34568EF1C4018F04F871FA05D41E

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

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 BC D6 09 00 B2 AF 9C 64
0010 | 78 01 00 00 1F 5F 04 F5 B0 BB 83 C2 68 49 38 B7
0020 | 6A C4 92 3A A5 45 C8 F0 59 2E 37 C5 BF 99 B8 DD
0030 | AE 33 E6 EE 39 4B 47 42 FE 50 01 00 B1 57 BF 35
0040 | 96 95 6D 48 DF 20 A9 E1 0A B5 07 97 11 28 D2 05
0050 | 30 E7 E3 B6 08 7F B1 BA 74 DB E7 74 DE 8C 5A 1A
0060 | C9 D0 1F 70 86 8E D3 68 1F C6 94 F3 0C E3 58 FC
0070 | 74 B8 54 DB 48 14 31 96 F4 55 5C B2 27 21 DB 87
0080 | E8 3D 14 28 6C BF B5 4F 4C 18 F5 1C 9E B7 19 C5
0090 | 92 4B 4E 54 6D 6B 07 3C 68 BA 93 19 8F B7 A9 1F
00A0 | B4 53 8E 88 F6 DA 2D CC F3 73 4F 7E A0 11 25 95
00B0 | DE DD 6E 69 C3 8A 5F 70 E1 50 70 69 C2 6E 84 7F
00C0 | B3 9E EF 4B E9 68 63 A8 98 FB 52 11 17 DA 52 89
00D0 | CA D8 F2 6F 3D 91 2D 33 14 A3 D4 E5 4D 81 20 2A
00E0 | B3 6E D3 62 57 04 73 0B CB 49 5D 34 64 43 3C B2
00F0 | CC 51 D1 A3 55 AD 78 8C 04 08 4C FF 69 AE AA 9A
0100 | C6 28 27 85 19 2B E1 C7 C1 E4 AC 14 E9 13 58 05
0110 | 6E 1A 4B C2 B0 D5 E9 84 0F 19 F7 02 57 AD 79 75
0120 | DA C3 33 8C 5B 39 38 35 29 6E 51 D4 84 5C 07 96
0130 | 2A 58 F8 8E E2 E2 E6 7C 46 B1 F4 4C BC A4 62 4D
0140 | 6B D8 CC 3B A6 B5 9B 63 5C AF F7 06 89 3E 63 68
0150 | 40 4F 04 75 97 5F 65 2D 4C 7C 69 C4 E8 FA 88 A9
0160 | 02 3B B8 98 95 82 31 32 B3 40 8C 03 26 A4 FE 9E
0170 | E6 8A DE BC 56 76 8F 03 29 C9 DB 79 10 8F 08 0F
0180 | CE E3 26 13 5F 10 E4 F8 9E 4C 9E F5

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 BCD60900B2AF9C64 Message ID generated as specified here »
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 B0BB83C2684938B76AC4923AA545C8F0 Value generated by client in Step 1
server_nonce 40, 16 592E37C5BF99B8DDAE33E6EE394B4742 Value received from server in Step 2
encrypted_data 56, 340 FE500100B157BF3596956D48DF20A9E1 0AB507971128D20530E7E3B6087FB1BA 74DBE774DE8C5A1AC9D01F70868ED368 1FC694F30CE358FC74B854DB48143196 F4555CB22721DB87E83D14286CBFB54F 4C18F51C9EB719C5924B4E546D6B073C 68BA93198FB7A91FB4538E88F6DA2DCC F3734F7EA0112595DEDD6E69C38A5F70 E1507069C26E847FB39EEF4BE96863A8 98FB521117DA5289CAD8F26F3D912D33 14A3D4E54D81202AB36ED3625704730B CB495D3464433CB2CC51D1A355AD788C 04084CFF69AEAA9AC6282785192BE1C7 C1E4AC14E91358056E1A4BC2B0D5E984 0F19F70257AD7975DAC3338C5B393835 296E51D4845C07962A58F88EE2E2E67C 46B1F44CBCA4624D6BD8CC3BA6B59B63 5CAFF706893E6368404F0475975F652D 4C7C69C4E8FA88A9023BB89895823132 B3408C0326A4FE9EE68ADEBC56768F03 29C9DB79108F080FCEE326135F10E4F8
9E4C9EF5
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 = 4B2FB207D87D159C14CFBC094533E4305721FD3F8CF1F4C2E218481DAD5BDE4BD687064C86A2F9B15DDF2EB43F6558C7EF91B99FADF614711AEDC6BBAE02F10B97EC40B81837695E58F11F2FAC48E949AF2DBC35E3A8476FF2C8C1CA85835634BEA918657C9801AD8876E8319C02ADF9209EAF5A3D429560D98816943C3019971B67372E146106CD27FB110A589DA8890F43348AF77143AFFCB08BEBEF89BD14BBFECC6AFE2B028C4BEC26ADC3D6786DABFF738CDAEBFE2D15806977DB496736716CD0B64938F1AEC6911FB56B70CC86BFB458048E970CD28E2F3844B7082493C1D46C0EA0AA798068C4160DA2C2D7562A6160255C6A1D7C3C47B7B8DD1C6D55
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 60 9B 67 B2 AF 9C 64
0010 | 34 00 00 00 34 F7 CB 3B B0 BB 83 C2 68 49 38 B7
0020 | 6A C4 92 3A A5 45 C8 F0 59 2E 37 C5 BF 99 B8 DD
0030 | AE 33 E6 EE 39 4B 47 42 6A F1 5D D5 EA 4A 58 6A
0040 | 27 E0 A1 DC 7E 26 D2 C4

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 01609B67B2AF9C64 Message ID generated as specified here »
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 B0BB83C2684938B76AC4923AA545C8F0 Value generated by client in Step 1
server_nonce 40, 16 592E37C5BF99B8DDAE33E6EE394B4742 Value received from server in Step 2
new_nonce_hash1 56, 16 6AF15DD5EA4A586A27E0A1DC7E26D2C4 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.