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 18 5C 07 00 20 79 CE 69
0010 | 14 00 00 00 F1 8E 7E BE 2B 30 67 5E 4D 27 E8 38
0020 | 69 41 A2 83 97 72 F6 BE

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 185C07002079CE69 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 2B30675E4D27E8386941A2839772F6BE 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 B4 6D 45 21 79 CE 69
0010 | 50 00 00 00 63 24 16 05 2B 30 67 5E 4D 27 E8 38
0020 | 69 41 A2 83 97 72 F6 BE 51 82 C8 82 09 6D A2 E2
0030 | 44 5B 01 87 AA 43 FC 5B 08 1B FF 37 DC B5 E6 8C
0040 | F1 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 01B46D452179CE69 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 2B30675E4D27E8386941A2839772F6BE Value generated by client in Step 1
server_nonce 40, 16 5182C882096DA2E2445B0187AA43FC5B Server-generated random number
pq 56, 12 081BFF37DCB5E68CF1000000
TL byte deserialization
=> bigendian conversion to decimal
=> 2017392579169389809
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 = 2017392579169389809

Decompose into 2 prime cofactors p < q: 2017392579169389809 = 1080628873 * 1866869033

p = 1080628873
q = 1866869033

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 1B FF 37 DC B5 E6 8C F1 00 00 00
0010 | 04 40 69 16 89 00 00 00 04 6F 46 29 29 00 00 00
0020 | 2B 30 67 5E 4D 27 E8 38 69 41 A2 83 97 72 F6 BE
0030 | 51 82 C8 82 09 6D A2 E2 44 5B 01 87 AA 43 FC 5B
0040 | 06 45 4C B7 5A 5B EF E0 45 F0 C8 A7 7A 66 DA CE
0050 | 4D 63 04 73 CD B5 E1 FA 33 DD 06 81 19 40 47 CB
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 081BFF37DCB5E68CF1000000
TL byte deserialization
=> bigendian conversion to decimal
=> 2017392579169389809
Single-byte prefix denoting length, 8-byte string, and three bytes of padding
p 16, 8 0440691689000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1080628873
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 24, 8 046F462929000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1866869033
Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
nonce 32, 16 2B30675E4D27E8386941A2839772F6BE Value generated by client in Step 1
server_nonce 48, 16 5182C882096DA2E2445B0187AA43FC5B Value received from server in Step 2
new_nonce 64, 32 06454CB75A5BEFE045F0C8A77A66DACE 4D630473CDB5E1FA33DD0681194047CB 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 = 955FF5A9081BFF37DCB5E68CF10000000440691689000000046F4629290000002B30675E4D27E8386941A2839772F6BE5182C882096DA2E2445B0187AA43FC5B06454CB75A5BEFE045F0C8A77A66DACE4D630473CDB5E1FA33DD0681194047CB02000000
random_padding_bytes = 67209BED957D7F43A5E40E76D3291F02337BC4F50B3DDEF131AB9735236FB0A948D5ADA65DD28697F6F523417DC2E58D91E8EA58F22374690472F563BF8FC49B2C041BACE669D3371B2451BCE986333EA1FC9C9A727D266BD9786965

And this is the output:

encrypted_data = 5F574F22C0F6715DABF73305DFA889B89B6E76423277D57EA25CB7396BDF8A8C633F643136031960E341382A610B29D9D4EE4D21587F46458B458B265D6EFA6FEF32A734F1D1EAA28FD6625BA440B5163DCA4829499FA46CC656D990A47C9D2D0847B3E6640244E0974884EFAB8B967B1195FBDDBC84E243D4470EE894448DDF138EC82AD81D1C2C6CF5215FF1F544A141B93EA34FDCFA3BD9D2CFFB7538DE45DE63715A12006926317A2BE3BA449169DCCE284A5167D5C0DF9B9F6A47750327808064C38B4853D61F3E075D8C5937A2CEA5AA8401624BFEEF6AC4ACC21EBF3F3E3D294397A4BAAC4648A08492F3F248373834D04F758A88613CDF99F7B8E93D

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 D8 28 02 00 21 79 CE 69
0010 | 40 01 00 00 BE E4 12 D7 2B 30 67 5E 4D 27 E8 38
0020 | 69 41 A2 83 97 72 F6 BE 51 82 C8 82 09 6D A2 E2
0030 | 44 5B 01 87 AA 43 FC 5B 04 40 69 16 89 00 00 00
0040 | 04 6F 46 29 29 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 5F 57 4F 22 C0 F6 71 5D AB F7 33 05
0060 | DF A8 89 B8 9B 6E 76 42 32 77 D5 7E A2 5C B7 39
0070 | 6B DF 8A 8C 63 3F 64 31 36 03 19 60 E3 41 38 2A
0080 | 61 0B 29 D9 D4 EE 4D 21 58 7F 46 45 8B 45 8B 26
0090 | 5D 6E FA 6F EF 32 A7 34 F1 D1 EA A2 8F D6 62 5B
00A0 | A4 40 B5 16 3D CA 48 29 49 9F A4 6C C6 56 D9 90
00B0 | A4 7C 9D 2D 08 47 B3 E6 64 02 44 E0 97 48 84 EF
00C0 | AB 8B 96 7B 11 95 FB DD BC 84 E2 43 D4 47 0E E8
00D0 | 94 44 8D DF 13 8E C8 2A D8 1D 1C 2C 6C F5 21 5F
00E0 | F1 F5 44 A1 41 B9 3E A3 4F DC FA 3B D9 D2 CF FB
00F0 | 75 38 DE 45 DE 63 71 5A 12 00 69 26 31 7A 2B E3
0100 | BA 44 91 69 DC CE 28 4A 51 67 D5 C0 DF 9B 9F 6A
0110 | 47 75 03 27 80 80 64 C3 8B 48 53 D6 1F 3E 07 5D
0120 | 8C 59 37 A2 CE A5 AA 84 01 62 4B FE EF 6A C4 AC
0130 | C2 1E BF 3F 3E 3D 29 43 97 A4 BA AC 46 48 A0 84
0140 | 92 F3 F2 48 37 38 34 D0 4F 75 8A 88 61 3C DF 99
0150 | F7 B8 E9 3D

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 D82802002179CE69 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 2B30675E4D27E8386941A2839772F6BE Value generated by client in Step 1
server_nonce 40, 16 5182C882096DA2E2445B0187AA43FC5B Value received from server in Step 2
p 56, 8 0440691689000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1080628873
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 64, 8 046F462929000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1866869033
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 FE0001005F574F22C0F6715DABF73305 DFA889B89B6E76423277D57EA25CB739 6BDF8A8C633F643136031960E341382A 610B29D9D4EE4D21587F46458B458B26 5D6EFA6FEF32A734F1D1EAA28FD6625B A440B5163DCA4829499FA46CC656D990 A47C9D2D0847B3E6640244E0974884EF AB8B967B1195FBDDBC84E243D4470EE8 94448DDF138EC82AD81D1C2C6CF5215F F1F544A141B93EA34FDCFA3BD9D2CFFB 7538DE45DE63715A12006926317A2BE3 BA449169DCCE284A5167D5C0DF9B9F6A 47750327808064C38B4853D61F3E075D 8C5937A2CEA5AA8401624BFEEF6AC4AC C21EBF3F3E3D294397A4BAAC4648A084 92F3F248373834D04F758A88613CDF99
F7B8E93D
Value generated above
6) Server responds with:

Received payload (excluding transport headers/trailers):

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

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 0170D1CA2179CE69 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 2B30675E4D27E8386941A2839772F6BE Value generated by client in Step 1
server_nonce 40, 16 5182C882096DA2E2445B0187AA43FC5B Value received from server in Step 2
encrypted_answer 56, 596 FE500200AD2C4AE4174E0450CAE44F99 7AAC05864CBDF1900E67EE7D037746F5 966D645204B7FDD95DAE3D70394D4120 3CF6BA7D34502338B8568C7B04408631 F582D096E2DEB79766314977DE20C465 1C587E9478A4F83F899E241BBD44F397 A618809C4C693F41AF735AA4D2757C6E E21B8A7188A3EC41FB0669EDA493C968 39305E570B6949249497221F0C189C09 F13742A67690A8DC512214A81F74AB3B 1304D0B167FB7B3FA71DCF295DBE7CB7 E72D5976CFC3358174018E4FE05FE7E0 12F2AB5B0660EAF2A283F101BC664588 A98E552F4AE13E87A7FD7ED0E0A1A93C F85E18A3AA7EFEC4B9F43D091324EA7A 85ED8A9048C5989F08E2DF01C4629891 894C0D508034E34E0C5FBFD62CDD22F0 8797A1E773D5766734062AE79EF7BFD2 224A3BA2AFF7410BD9FA68F5AD6CDB77 C39E34C096F5370E8B0EDA66E49478F6 54FE7D165FE8D2CAF7F9FEEA09F0B4CD 4EAF7FD25FBB1D8F3A1D1E4B461C2AC8 991BAEC2949C6EF9C6A7918EC83258E6 E872660F4E91E4849C10AD0F7D8CBCE9 6F508D370F89DAE09120E8E29C185FE5 B7F8FABD69A871B3B57C402727D3D7F9 F4C3F63754C8D956CF6A2FCFA877B60C 0CCEDA5269C7982CE75432F2F14AD0E7 B766709506983EC0057E1EF85108BB28 6F2E3F7350F92227750A3C583BDB15B5 27889F074A1613E95A63366701063E1D 43948D91791227C19A9997B7A446A4A9 E4C1F4F168E1AC317A2C69FB11037774 770826B42E697516008628DB0586544D F8788893A667C31EEF07EE2192A4CE52 4D9777B7522EE43155441D1C8FC37ECB 3597F7C23A9A52C1215A18DE42B2A195
83199C1C
See below

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

encrypted_answer = AD2C4AE4174E0450CAE44F997AAC05864CBDF1900E67EE7D037746F5966D645204B7FDD95DAE3D70394D41203CF6BA7D34502338B8568C7B04408631F582D096E2DEB79766314977DE20C4651C587E9478A4F83F899E241BBD44F397A618809C4C693F41AF735AA4D2757C6EE21B8A7188A3EC41FB0669EDA493C96839305E570B6949249497221F0C189C09F13742A67690A8DC512214A81F74AB3B1304D0B167FB7B3FA71DCF295DBE7CB7E72D5976CFC3358174018E4FE05FE7E012F2AB5B0660EAF2A283F101BC664588A98E552F4AE13E87A7FD7ED0E0A1A93CF85E18A3AA7EFEC4B9F43D091324EA7A85ED8A9048C5989F08E2DF01C4629891894C0D508034E34E0C5FBFD62CDD22F08797A1E773D5766734062AE79EF7BFD2224A3BA2AFF7410BD9FA68F5AD6CDB77C39E34C096F5370E8B0EDA66E49478F654FE7D165FE8D2CAF7F9FEEA09F0B4CD4EAF7FD25FBB1D8F3A1D1E4B461C2AC8991BAEC2949C6EF9C6A7918EC83258E6E872660F4E91E4849C10AD0F7D8CBCE96F508D370F89DAE09120E8E29C185FE5B7F8FABD69A871B3B57C402727D3D7F9F4C3F63754C8D956CF6A2FCFA877B60C0CCEDA5269C7982CE75432F2F14AD0E7B766709506983EC0057E1EF85108BB286F2E3F7350F92227750A3C583BDB15B527889F074A1613E95A63366701063E1D43948D91791227C19A9997B7A446A4A9E4C1F4F168E1AC317A2C69FB11037774770826B42E697516008628DB0586544DF8788893A667C31EEF07EE2192A4CE524D9777B7522EE43155441D1C8FC37ECB3597F7C23A9A52C1215A18DE42B2A19583199C1C
tmp_aes_key = 9B4FAD35375D16E2CD02AB501CA2B8EF91A107F3422EEA9F20872B11DA335872
tmp_aes_iv = B5AF2B9DBF0D6BC17B0E36DE3901B7A7E38390ACD82BF1A83B61317706454CB7

Yielding:

answer_with_hash = B2E328E76397D10965AFAE8C3C1DA6874A4DC737BA0D89B52B30675E4D27E8386941A2839772F6BE5182C882096DA2E2445B0187AA43FC5B03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE00010097333185CD8CCB9123BF3F50F90E5FBC30F6E84E345FDFACBC0A96F4C2D89971D9A93150009D8CDD60420C492DEA2F15DCEF30D46927D8926899FAFED1EF33BC76F010EA2F3680533D6A6AF3111A4138D748866410B0F390BD46E431D8F88846E1FCF4B3A5073543927955DFD55F2AF1B0856773F515DCDB254702593F93A62D73A6FC981145E0E385AB70447EF68F4DEB0734D857AD3FB856DB1A2B1732F69FA859B06CF4C8912FABE329799721629CF611F217706C8E89C6653614F3AB6B09B8DACD98263088CF5B057D7AC1E7E4A3BAFF6E57B564C9853C91C92B80852A9B111ECDE15F55B684A73539134BCF676A3427C8D410D0734E0914E383C727B5102179CE6925287EE57928AF86
answer = BA0D89B52B30675E4D27E8386941A2839772F6BE5182C882096DA2E2445B0187AA43FC5B03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE00010097333185CD8CCB9123BF3F50F90E5FBC30F6E84E345FDFACBC0A96F4C2D89971D9A93150009D8CDD60420C492DEA2F15DCEF30D46927D8926899FAFED1EF33BC76F010EA2F3680533D6A6AF3111A4138D748866410B0F390BD46E431D8F88846E1FCF4B3A5073543927955DFD55F2AF1B0856773F515DCDB254702593F93A62D73A6FC981145E0E385AB70447EF68F4DEB0734D857AD3FB856DB1A2B1732F69FA859B06CF4C8912FABE329799721629CF611F217706C8E89C6653614F3AB6B09B8DACD98263088CF5B057D7AC1E7E4A3BAFF6E57B564C9853C91C92B80852A9B111ECDE15F55B684A73539134BCF676A3427C8D410D0734E0914E383C727B5102179CE6925287EE57928AF86

Generated payload (excluding transport headers/trailers):

0000 | BA 0D 89 B5 2B 30 67 5E 4D 27 E8 38 69 41 A2 83
0010 | 97 72 F6 BE 51 82 C8 82 09 6D A2 E2 44 5B 01 87
0020 | AA 43 FC 5B 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 | 97 33 31 85 CD 8C CB 91 23 BF 3F 50 F9 0E 5F BC
0140 | 30 F6 E8 4E 34 5F DF AC BC 0A 96 F4 C2 D8 99 71
0150 | D9 A9 31 50 00 9D 8C DD 60 42 0C 49 2D EA 2F 15
0160 | DC EF 30 D4 69 27 D8 92 68 99 FA FE D1 EF 33 BC
0170 | 76 F0 10 EA 2F 36 80 53 3D 6A 6A F3 11 1A 41 38
0180 | D7 48 86 64 10 B0 F3 90 BD 46 E4 31 D8 F8 88 46
0190 | E1 FC F4 B3 A5 07 35 43 92 79 55 DF D5 5F 2A F1
01A0 | B0 85 67 73 F5 15 DC DB 25 47 02 59 3F 93 A6 2D
01B0 | 73 A6 FC 98 11 45 E0 E3 85 AB 70 44 7E F6 8F 4D
01C0 | EB 07 34 D8 57 AD 3F B8 56 DB 1A 2B 17 32 F6 9F
01D0 | A8 59 B0 6C F4 C8 91 2F AB E3 29 79 97 21 62 9C
01E0 | F6 11 F2 17 70 6C 8E 89 C6 65 36 14 F3 AB 6B 09
01F0 | B8 DA CD 98 26 30 88 CF 5B 05 7D 7A C1 E7 E4 A3
0200 | BA FF 6E 57 B5 64 C9 85 3C 91 C9 2B 80 85 2A 9B
0210 | 11 1E CD E1 5F 55 B6 84 A7 35 39 13 4B CF 67 6A
0220 | 34 27 C8 D4 10 D0 73 4E 09 14 E3 83 C7 27 B5 10
0230 | 21 79 CE 69

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 2B30675E4D27E8386941A2839772F6BE Value generated by client in Step 1
server_nonce 20, 16 5182C882096DA2E2445B0187AA43FC5B 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 FE00010097333185CD8CCB9123BF3F50 F90E5FBC30F6E84E345FDFACBC0A96F4 C2D89971D9A93150009D8CDD60420C49 2DEA2F15DCEF30D46927D8926899FAFE D1EF33BC76F010EA2F3680533D6A6AF3 111A4138D748866410B0F390BD46E431 D8F88846E1FCF4B3A5073543927955DF D55F2AF1B0856773F515DCDB25470259 3F93A62D73A6FC981145E0E385AB7044 7EF68F4DEB0734D857AD3FB856DB1A2B 1732F69FA859B06CF4C8912FABE32979 9721629CF611F217706C8E89C6653614 F3AB6B09B8DACD98263088CF5B057D7A C1E7E4A3BAFF6E57B564C9853C91C92B 80852A9B111ECDE15F55B684A7353913 4BCF676A3427C8D410D0734E0914E383
C727B510
g_a diffie-hellman parameter
server_time 560, 4 2179CE69 (1775139105 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 = 61E2C4AD3F1A02412533A487F7F367BDE56A0E0AB0210ED87BE09EEE48F829D4FEE0F9D451DC3BAE42031CB2582320AD410D285FC2911CDBC1A0E686328D9933D15F5E27FC3E6CEC357A9B81E68C3335E12FB3C739CF95AF333779A4442F09E05A777461D99D34B10C011B3B54B81360086ADCE1A0A695BC67E4276C1BD1EC6DF8FE28F217CFD56CF7E8E0F880059F5AB8E856F80A0B8521DC6A0270FF00B9CA655E14A518E95026EBFFBD658EB6B561361891AD100C58B34A642550651B2985964A3D3CBFD0FCFC1B5806DD8A71E4C5D64CA7B61E24E1A639C6128574709412A31EAF20C4A8FDA8BE2E298E65F82819515E7534F3085584D00BF17DC160FE94

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

g_b = 60B5E327BB0819BE885EC484C9C0550BA85563F5176DEE9F266CF44F3D00C83DFC7CFF797DB8F467CEEC8A251EC0A1508080B4FCDB2330CBA1F300E197B3452383925EA3FC9E859B6D4E737880D70F67A557D70B418797C0739D562C5464AB037ED36787481011E7B25874F605FD20309EFFDD31284DC306A7A0CC0E3CC1CDCA94DC82393FB3AA80E869E69CD755DC24349834C92FF3E2E8CB7115CF021FA10C2C7A5552525EA1CF2CD71EB46431DCB86A1679AA6FEB40987A28968C07533F0682DC1983FB3E1D8C57F1AF544D60C83E4886A872585E4B934F0D6D38D37B51E4046CBA882F4209B5964EF3547C096B52844FAE3868A08A2521463D6862938EBA
7.1) generation of encrypted_data

Generated payload (excluding transport headers/trailers):

0000 | 54 B6 43 66 2B 30 67 5E 4D 27 E8 38 69 41 A2 83
0010 | 97 72 F6 BE 51 82 C8 82 09 6D A2 E2 44 5B 01 87
0020 | AA 43 FC 5B 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | 60 B5 E3 27 BB 08 19 BE 88 5E C4 84 C9 C0 55 0B
0040 | A8 55 63 F5 17 6D EE 9F 26 6C F4 4F 3D 00 C8 3D
0050 | FC 7C FF 79 7D B8 F4 67 CE EC 8A 25 1E C0 A1 50
0060 | 80 80 B4 FC DB 23 30 CB A1 F3 00 E1 97 B3 45 23
0070 | 83 92 5E A3 FC 9E 85 9B 6D 4E 73 78 80 D7 0F 67
0080 | A5 57 D7 0B 41 87 97 C0 73 9D 56 2C 54 64 AB 03
0090 | 7E D3 67 87 48 10 11 E7 B2 58 74 F6 05 FD 20 30
00A0 | 9E FF DD 31 28 4D C3 06 A7 A0 CC 0E 3C C1 CD CA
00B0 | 94 DC 82 39 3F B3 AA 80 E8 69 E6 9C D7 55 DC 24
00C0 | 34 98 34 C9 2F F3 E2 E8 CB 71 15 CF 02 1F A1 0C
00D0 | 2C 7A 55 52 52 5E A1 CF 2C D7 1E B4 64 31 DC B8
00E0 | 6A 16 79 AA 6F EB 40 98 7A 28 96 8C 07 53 3F 06
00F0 | 82 DC 19 83 FB 3E 1D 8C 57 F1 AF 54 4D 60 C8 3E
0100 | 48 86 A8 72 58 5E 4B 93 4F 0D 6D 38 D3 7B 51 E4
0110 | 04 6C BA 88 2F 42 09 B5 96 4E F3 54 7C 09 6B 52
0120 | 84 4F AE 38 68 A0 8A 25 21 46 3D 68 62 93 8E BA

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 2B30675E4D27E8386941A2839772F6BE Value generated by client in Step 1
server_nonce 20, 16 5182C882096DA2E2445B0187AA43FC5B Value received from server in Step 2
g_b 36, 260 FE00010060B5E327BB0819BE885EC484 C9C0550BA85563F5176DEE9F266CF44F 3D00C83DFC7CFF797DB8F467CEEC8A25 1EC0A1508080B4FCDB2330CBA1F300E1 97B3452383925EA3FC9E859B6D4E7378 80D70F67A557D70B418797C0739D562C 5464AB037ED36787481011E7B25874F6 05FD20309EFFDD31284DC306A7A0CC0E 3CC1CDCA94DC82393FB3AA80E869E69C D755DC24349834C92FF3E2E8CB7115CF 021FA10C2C7A5552525EA1CF2CD71EB4 6431DCB86A1679AA6FEB40987A28968C 07533F0682DC1983FB3E1D8C57F1AF54 4D60C83E4886A872585E4B934F0D6D38 D37B51E4046CBA882F4209B5964EF354 7C096B52844FAE3868A08A2521463D68
62938EBA
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 = 54B643662B30675E4D27E8386941A2839772F6BE5182C882096DA2E2445B0187AA43FC5B0000000000000000FE00010060B5E327BB0819BE885EC484C9C0550BA85563F5176DEE9F266CF44F3D00C83DFC7CFF797DB8F467CEEC8A251EC0A1508080B4FCDB2330CBA1F300E197B3452383925EA3FC9E859B6D4E737880D70F67A557D70B418797C0739D562C5464AB037ED36787481011E7B25874F605FD20309EFFDD31284DC306A7A0CC0E3CC1CDCA94DC82393FB3AA80E869E69CD755DC24349834C92FF3E2E8CB7115CF021FA10C2C7A5552525EA1CF2CD71EB46431DCB86A1679AA6FEB40987A28968C07533F0682DC1983FB3E1D8C57F1AF544D60C83E4886A872585E4B934F0D6D38D37B51E4046CBA882F4209B5964EF3547C096B52844FAE3868A08A2521463D6862938EBA
padding = 8BB5CDCC52B73FDBEDCE8A00
tmp_aes_key = 9B4FAD35375D16E2CD02AB501CA2B8EF91A107F3422EEA9F20872B11DA335872
tmp_aes_iv = B5AF2B9DBF0D6BC17B0E36DE3901B7A7E38390ACD82BF1A83B61317706454CB7

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 = 50A369D6A2E5F79FEFC156B9BCA2CDCDE782EFBE244549649EE71D7823F23B9FE8ABE123D3BF431505088ED4ED99EA448D2879C51C66B34FA314350A9D9FE6A5B1FA0C198869326D02C96DE3BD9D746276FC479E518AF4599C4DC1B7093556378AEB75769101BACA683D985B68E7850588547D44D34F379DC2FAC1E3BD5CBDFE37412115315EE000878546604E220F944E142A666FD89DCA6B52A89547C891B2C292C544BE5989413A4AD5BB093055A59168E521A92CCC8522C816A33072ABCD2B9994B0D02EFFC68256BE4780C7C7291B24E30CA44358C7FB98C67AE8C0AA3081051BD5324DEEEB85CBCC1C3226C846037392CFFBA56406DD18FE75825C5601F14B546FF69F658C8700B16585C9380F9C54C8DF36CE51554F845F91091416567739B6B46263D2FCF91867AFF0B48181C8F9D2E91415E4515AEA1A459DE0DBDE8952E03CC1D63DFB25CE892E553EA973

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 B8 B0 06 00 21 79 CE 69
0010 | 78 01 00 00 1F 5F 04 F5 2B 30 67 5E 4D 27 E8 38
0020 | 69 41 A2 83 97 72 F6 BE 51 82 C8 82 09 6D A2 E2
0030 | 44 5B 01 87 AA 43 FC 5B FE 50 01 00 50 A3 69 D6
0040 | A2 E5 F7 9F EF C1 56 B9 BC A2 CD CD E7 82 EF BE
0050 | 24 45 49 64 9E E7 1D 78 23 F2 3B 9F E8 AB E1 23
0060 | D3 BF 43 15 05 08 8E D4 ED 99 EA 44 8D 28 79 C5
0070 | 1C 66 B3 4F A3 14 35 0A 9D 9F E6 A5 B1 FA 0C 19
0080 | 88 69 32 6D 02 C9 6D E3 BD 9D 74 62 76 FC 47 9E
0090 | 51 8A F4 59 9C 4D C1 B7 09 35 56 37 8A EB 75 76
00A0 | 91 01 BA CA 68 3D 98 5B 68 E7 85 05 88 54 7D 44
00B0 | D3 4F 37 9D C2 FA C1 E3 BD 5C BD FE 37 41 21 15
00C0 | 31 5E E0 00 87 85 46 60 4E 22 0F 94 4E 14 2A 66
00D0 | 6F D8 9D CA 6B 52 A8 95 47 C8 91 B2 C2 92 C5 44
00E0 | BE 59 89 41 3A 4A D5 BB 09 30 55 A5 91 68 E5 21
00F0 | A9 2C CC 85 22 C8 16 A3 30 72 AB CD 2B 99 94 B0
0100 | D0 2E FF C6 82 56 BE 47 80 C7 C7 29 1B 24 E3 0C
0110 | A4 43 58 C7 FB 98 C6 7A E8 C0 AA 30 81 05 1B D5
0120 | 32 4D EE EB 85 CB CC 1C 32 26 C8 46 03 73 92 CF
0130 | FB A5 64 06 DD 18 FE 75 82 5C 56 01 F1 4B 54 6F
0140 | F6 9F 65 8C 87 00 B1 65 85 C9 38 0F 9C 54 C8 DF
0150 | 36 CE 51 55 4F 84 5F 91 09 14 16 56 77 39 B6 B4
0160 | 62 63 D2 FC F9 18 67 AF F0 B4 81 81 C8 F9 D2 E9
0170 | 14 15 E4 51 5A EA 1A 45 9D E0 DB DE 89 52 E0 3C
0180 | C1 D6 3D FB 25 CE 89 2E 55 3E A9 73

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 B8B006002179CE69 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 2B30675E4D27E8386941A2839772F6BE Value generated by client in Step 1
server_nonce 40, 16 5182C882096DA2E2445B0187AA43FC5B Value received from server in Step 2
encrypted_data 56, 340 FE50010050A369D6A2E5F79FEFC156B9 BCA2CDCDE782EFBE244549649EE71D78 23F23B9FE8ABE123D3BF431505088ED4 ED99EA448D2879C51C66B34FA314350A 9D9FE6A5B1FA0C198869326D02C96DE3 BD9D746276FC479E518AF4599C4DC1B7 093556378AEB75769101BACA683D985B 68E7850588547D44D34F379DC2FAC1E3 BD5CBDFE37412115315EE00087854660 4E220F944E142A666FD89DCA6B52A895 47C891B2C292C544BE5989413A4AD5BB 093055A59168E521A92CCC8522C816A3 3072ABCD2B9994B0D02EFFC68256BE47 80C7C7291B24E30CA44358C7FB98C67A E8C0AA3081051BD5324DEEEB85CBCC1C 3226C846037392CFFBA56406DD18FE75 825C5601F14B546FF69F658C8700B165 85C9380F9C54C8DF36CE51554F845F91 091416567739B6B46263D2FCF91867AF F0B48181C8F9D2E91415E4515AEA1A45 9DE0DBDE8952E03CC1D63DFB25CE892E
553EA973
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 = 5A9A31330C86E2612903C4BD1F17A55E453E9185B288C6044F718F1CA0C8423246886CA17B190532757479DCF55A455A5A02CE3B18937D77F4F91C37A5E019337679151547ECD1DC153A46A01AFDB8D31ABCF1F6EBC6950FD1C3F1448CFAA74205309828939CD4E39DB94D9E8D97282ABCC994C6A80B719E5B393B99BC34613AABCE0EC130B11DC1550CF1847BA3D7A89C68FDC0126DBCC38E31ADBC3872F426522DB3B48703CFBDCC717E372595F384559D3BF41B2BCC8A816B2E48FFFE26019B91859BB73980D39599A17C9B5564F6B9CBC8245A33BA16D4DA1DDFB8D2835466329051BCF9CC20ED6B6844AC75BBEDE68D5E84622666763768AE9C82B0ECA9
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 40 A3 24 23 79 CE 69
0010 | 34 00 00 00 34 F7 CB 3B 2B 30 67 5E 4D 27 E8 38
0020 | 69 41 A2 83 97 72 F6 BE 51 82 C8 82 09 6D A2 E2
0030 | 44 5B 01 87 AA 43 FC 5B 0F 38 DC 7F 66 21 2F 2B
0040 | 3E D2 94 45 A6 FF 17 DA

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 0140A3242379CE69 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 2B30675E4D27E8386941A2839772F6BE Value generated by client in Step 1
server_nonce 40, 16 5182C882096DA2E2445B0187AA43FC5B Value received from server in Step 2
new_nonce_hash1 56, 16 0F38DC7F66212F2B3ED29445A6FF17DA 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.