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 1C 03 0F 00 8A 63 64 67
0010 | 14 00 00 00 F1 8E 7E BE 33 07 FA CD 89 37 59 11
0020 | 1C 45 C7 36 11 C6 52 D3

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 1C030F008A636467 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 3307FACD893759111C45C73611C652D3 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 88 A9 86 8A 63 64 67
0010 | 50 00 00 00 63 24 16 05 33 07 FA CD 89 37 59 11
0020 | 1C 45 C7 36 11 C6 52 D3 21 11 41 41 1C 35 33 2C
0030 | B8 E0 5D A1 A9 E7 09 44 08 15 24 F7 62 B5 2E 7F
0040 | B9 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 0188A9868A636467 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 3307FACD893759111C45C73611C652D3 Value generated by client in Step 1
server_nonce 40, 16 211141411C35332CB8E05DA1A9E70944 Server-generated random number
pq 56, 12 081524F762B52E7FB9000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1523614577276649401
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 = 1523614577276649401

Decompose into 2 prime cofactors p < q: 1523614577276649401 = 1102606273 * 1381830137

p = 1102606273
q = 1381830137

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 15 24 F7 62 B5 2E 7F B9 00 00 00
0010 | 04 41 B8 6F C1 00 00 00 04 52 5D 0D F9 00 00 00
0020 | 33 07 FA CD 89 37 59 11 1C 45 C7 36 11 C6 52 D3
0030 | 21 11 41 41 1C 35 33 2C B8 E0 5D A1 A9 E7 09 44
0040 | 4B CA BA 6D C6 3E 71 D0 D7 D6 CC 3F D3 7D AB 14
0050 | 17 6F 1C 1C F3 DE 9A 52 E1 6D E7 F8 7C 98 C1 72
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 081524F762B52E7FB9000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1523614577276649401
Single-byte prefix denoting length, 8-byte string, and three bytes of padding
p 16, 8 0441B86FC1000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1102606273
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 24, 8 04525D0DF9000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1381830137
Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
nonce 32, 16 3307FACD893759111C45C73611C652D3 Value generated by client in Step 1
server_nonce 48, 16 211141411C35332CB8E05DA1A9E70944 Value received from server in Step 2
new_nonce 64, 32 4BCABA6DC63E71D0D7D6CC3FD37DAB14 176F1C1CF3DE9A52E16DE7F87C98C172 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 = 955FF5A9081524F762B52E7FB90000000441B86FC100000004525D0DF90000003307FACD893759111C45C73611C652D3211141411C35332CB8E05DA1A9E709444BCABA6DC63E71D0D7D6CC3FD37DAB14176F1C1CF3DE9A52E16DE7F87C98C17202000000
random_padding_bytes = 678A898401B74C2BF18FF7681A4B13F3DE29D98D07AC9C6A50CF4F4F4A47D28B5077DF678548B998E6E57F363E338CDC7E4906F3AAE5238165D38F11353256D1AB8AB12C493C3D740596D33A8B201B8CB562E4D20ECB342839003F03

And this is the output:

encrypted_data = DF5CB249FA013D9E99D341BC19B92BF6BA791CE8722C83FB9BC97129B08D82D5F956B2C7DDAF72B3D18E173568C28F0E71A547455D39AE6B69A5392CCB26424249C1F6352F0CA1A83E9AB6E0910FDEDF101AA2214B0177EDC616225B8ABA66B4AFD55EDEABF39A2902277FB8182E1BB67E58E3C8C7230D4AE19AAAB8F19E0DECE697A168998305C0770B3F344F586BD7C6CC9A13C87D151A2133CD7A37FC03BB1BD5E062943223E6457CE0EDB1C6F8C6809366BA833D83EBB1261C6A7E755A39357F211B4A60B02938CF961D69264DC9A740A7B6817651ADA0D5BF2D2BF7AAB8AB969442737C353B000F614704E7152B940B03FDDBF706DBF09BFA69F7333652

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 20 03 0F 00 8A 63 64 67
0010 | 40 01 00 00 BE E4 12 D7 33 07 FA CD 89 37 59 11
0020 | 1C 45 C7 36 11 C6 52 D3 21 11 41 41 1C 35 33 2C
0030 | B8 E0 5D A1 A9 E7 09 44 04 41 B8 6F C1 00 00 00
0040 | 04 52 5D 0D F9 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 DF 5C B2 49 FA 01 3D 9E 99 D3 41 BC
0060 | 19 B9 2B F6 BA 79 1C E8 72 2C 83 FB 9B C9 71 29
0070 | B0 8D 82 D5 F9 56 B2 C7 DD AF 72 B3 D1 8E 17 35
0080 | 68 C2 8F 0E 71 A5 47 45 5D 39 AE 6B 69 A5 39 2C
0090 | CB 26 42 42 49 C1 F6 35 2F 0C A1 A8 3E 9A B6 E0
00A0 | 91 0F DE DF 10 1A A2 21 4B 01 77 ED C6 16 22 5B
00B0 | 8A BA 66 B4 AF D5 5E DE AB F3 9A 29 02 27 7F B8
00C0 | 18 2E 1B B6 7E 58 E3 C8 C7 23 0D 4A E1 9A AA B8
00D0 | F1 9E 0D EC E6 97 A1 68 99 83 05 C0 77 0B 3F 34
00E0 | 4F 58 6B D7 C6 CC 9A 13 C8 7D 15 1A 21 33 CD 7A
00F0 | 37 FC 03 BB 1B D5 E0 62 94 32 23 E6 45 7C E0 ED
0100 | B1 C6 F8 C6 80 93 66 BA 83 3D 83 EB B1 26 1C 6A
0110 | 7E 75 5A 39 35 7F 21 1B 4A 60 B0 29 38 CF 96 1D
0120 | 69 26 4D C9 A7 40 A7 B6 81 76 51 AD A0 D5 BF 2D
0130 | 2B F7 AA B8 AB 96 94 42 73 7C 35 3B 00 0F 61 47
0140 | 04 E7 15 2B 94 0B 03 FD DB F7 06 DB F0 9B FA 69
0150 | F7 33 36 52

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 20030F008A636467 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 3307FACD893759111C45C73611C652D3 Value generated by client in Step 1
server_nonce 40, 16 211141411C35332CB8E05DA1A9E70944 Value received from server in Step 2
p 56, 8 0441B86FC1000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1102606273
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 64, 8 04525D0DF9000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1381830137
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 FE000100DF5CB249FA013D9E99D341BC 19B92BF6BA791CE8722C83FB9BC97129 B08D82D5F956B2C7DDAF72B3D18E1735 68C28F0E71A547455D39AE6B69A5392C CB26424249C1F6352F0CA1A83E9AB6E0 910FDEDF101AA2214B0177EDC616225B 8ABA66B4AFD55EDEABF39A2902277FB8 182E1BB67E58E3C8C7230D4AE19AAAB8 F19E0DECE697A168998305C0770B3F34 4F586BD7C6CC9A13C87D151A2133CD7A 37FC03BB1BD5E062943223E6457CE0ED B1C6F8C6809366BA833D83EBB1261C6A 7E755A39357F211B4A60B02938CF961D 69264DC9A740A7B6817651ADA0D5BF2D 2BF7AAB8AB969442737C353B000F6147 04E7152B940B03FDDBF706DBF09BFA69
F7333652
Value generated above
6) Server responds with:

Received payload (excluding transport headers/trailers):

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

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 01C471998A636467 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 3307FACD893759111C45C73611C652D3 Value generated by client in Step 1
server_nonce 40, 16 211141411C35332CB8E05DA1A9E70944 Value received from server in Step 2
encrypted_answer 56, 596 FE5002005071B8A71CFAF9E8F7A3E694 F238BC445AE7587CEEBEBDA7455B518D 5A5B571803C0E9629D44EBE923D16547 3BCCF4308E3050D8079153FEDA33BCB3 69414C9BA5C1AECD1335DA76CA717AA6 E576FBD1C603082F089542C894EBF18C 8D14378DF9CF54E804BC5C435F5BA380 273B9E239048E1E310F62C0BF400443E F0F3117436202890139CE8753E51E225 DC391DA310E687F838EFFD2C33013F4E 5B85672E56240125C7DDDFFF307CDA78 2BB25C0A4063D7A09052916D61BAE006 9B1AE068C8E482B9B3A9D9A5F3B6BE7A EB62B267C03DA1FE6B65416BD1BCBA56 7CACDBB688E9F3F565F7B08AB4946283 2648892B866C27C78453B021E0FE861F C6D341884A54471697280D05FA019E7E CD395FA8C191D39C253DF2573AA66551 CEBAF563F7D1AD47C9064E91AFE00BE6 DD7F0B8613553717D97A14E0DBB25520 D8B92977D147BC3E2ACD4CB4585A29D7 9086A1F99E3A3AE087A26F55488796B7 B1A564D9A499026E0031B332F6E05F11 91BF6FFF6D32472472F1314EFB9CBB52 2262A0220A7C6F7F755F9E2619E76B0D DDCB71CDEC5FE26B6BF4C16415578138 EF7D63E2A45AE5E15F4757241773D9B3 367EDEA026747DE4598EE32B4C95CBA6 63569C25426656EB9FF5C8B97023A3D0 64C82A0413E86643E1133C9EBC633AC2 156626BF440A4FCF195A51E8AB7B0D89 35A7F649EA049281FD0A19D9A9861356 DD48D052151589311E37DEEBFCD13282 288FC007F030285653154C5A91A9A535 4A35A2232ACA43283DED4CFBD4BF6360 2D94486880C8EAF2D5591055BC0F8C96 C8D11FBB2787CD5DB591B54D46A62C56
75C4F4CB
See below

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

encrypted_answer = 5071B8A71CFAF9E8F7A3E694F238BC445AE7587CEEBEBDA7455B518D5A5B571803C0E9629D44EBE923D165473BCCF4308E3050D8079153FEDA33BCB369414C9BA5C1AECD1335DA76CA717AA6E576FBD1C603082F089542C894EBF18C8D14378DF9CF54E804BC5C435F5BA380273B9E239048E1E310F62C0BF400443EF0F3117436202890139CE8753E51E225DC391DA310E687F838EFFD2C33013F4E5B85672E56240125C7DDDFFF307CDA782BB25C0A4063D7A09052916D61BAE0069B1AE068C8E482B9B3A9D9A5F3B6BE7AEB62B267C03DA1FE6B65416BD1BCBA567CACDBB688E9F3F565F7B08AB49462832648892B866C27C78453B021E0FE861FC6D341884A54471697280D05FA019E7ECD395FA8C191D39C253DF2573AA66551CEBAF563F7D1AD47C9064E91AFE00BE6DD7F0B8613553717D97A14E0DBB25520D8B92977D147BC3E2ACD4CB4585A29D79086A1F99E3A3AE087A26F55488796B7B1A564D9A499026E0031B332F6E05F1191BF6FFF6D32472472F1314EFB9CBB522262A0220A7C6F7F755F9E2619E76B0DDDCB71CDEC5FE26B6BF4C16415578138EF7D63E2A45AE5E15F4757241773D9B3367EDEA026747DE4598EE32B4C95CBA663569C25426656EB9FF5C8B97023A3D064C82A0413E86643E1133C9EBC633AC2156626BF440A4FCF195A51E8AB7B0D8935A7F649EA049281FD0A19D9A9861356DD48D052151589311E37DEEBFCD13282288FC007F030285653154C5A91A9A5354A35A2232ACA43283DED4CFBD4BF63602D94486880C8EAF2D5591055BC0F8C96C8D11FBB2787CD5DB591B54D46A62C5675C4F4CB
tmp_aes_key = 0795629A5D2239A3C7D6621F456F374BBD159029604769225852B522FF4022D0
tmp_aes_iv = D36212548C7DA3DE584E6019C796C74F44C700A45123F014532F979D4BCABA6D

Yielding:

answer_with_hash = 6DDD9D0BD12466767136EFA07EB94444FA562161BA0D89B53307FACD893759111C45C73611C652D3211141411C35332CB8E05DA1A9E7094403000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE00010068655C507A7B28EDEFD23CBAB33292A68F753AACC95AA74E1D035C1D31F400424F82B81775FB9D31C34B89D3C74BD411D0810F552F2CF053A956DD4450FFFFACFB3A26AE8A23FF0492A8E34CDD8CEDA402CFA72435801BCFD534FB49C9C0326EFD7D5D0C727B8EFC8D7B71132AF16B0BF40B9710E425F7EFC5E607754A326CD85258EDF6DB100E1847206FF6EBE83CE8D244A493665ED55D58018D43293F61ABA2507D0EEE9E62149E23DC089E3F017CEEFF39A94986BAC8EEC19D0DAE24A3A1062FC4BDE16AF8CACB5C12ACCCF6BB1D124D4E9EA3B96746C60128B56692F1169ED7741B154ECD68401D5ED9668FDE8CE1FE656FECD8C3EDF4AFD29CE2CEE6E08A636467A67622677A647EA5
answer = BA0D89B53307FACD893759111C45C73611C652D3211141411C35332CB8E05DA1A9E7094403000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE00010068655C507A7B28EDEFD23CBAB33292A68F753AACC95AA74E1D035C1D31F400424F82B81775FB9D31C34B89D3C74BD411D0810F552F2CF053A956DD4450FFFFACFB3A26AE8A23FF0492A8E34CDD8CEDA402CFA72435801BCFD534FB49C9C0326EFD7D5D0C727B8EFC8D7B71132AF16B0BF40B9710E425F7EFC5E607754A326CD85258EDF6DB100E1847206FF6EBE83CE8D244A493665ED55D58018D43293F61ABA2507D0EEE9E62149E23DC089E3F017CEEFF39A94986BAC8EEC19D0DAE24A3A1062FC4BDE16AF8CACB5C12ACCCF6BB1D124D4E9EA3B96746C60128B56692F1169ED7741B154ECD68401D5ED9668FDE8CE1FE656FECD8C3EDF4AFD29CE2CEE6E08A636467A67622677A647EA5

Generated payload (excluding transport headers/trailers):

0000 | BA 0D 89 B5 33 07 FA CD 89 37 59 11 1C 45 C7 36
0010 | 11 C6 52 D3 21 11 41 41 1C 35 33 2C B8 E0 5D A1
0020 | A9 E7 09 44 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 | 68 65 5C 50 7A 7B 28 ED EF D2 3C BA B3 32 92 A6
0140 | 8F 75 3A AC C9 5A A7 4E 1D 03 5C 1D 31 F4 00 42
0150 | 4F 82 B8 17 75 FB 9D 31 C3 4B 89 D3 C7 4B D4 11
0160 | D0 81 0F 55 2F 2C F0 53 A9 56 DD 44 50 FF FF AC
0170 | FB 3A 26 AE 8A 23 FF 04 92 A8 E3 4C DD 8C ED A4
0180 | 02 CF A7 24 35 80 1B CF D5 34 FB 49 C9 C0 32 6E
0190 | FD 7D 5D 0C 72 7B 8E FC 8D 7B 71 13 2A F1 6B 0B
01A0 | F4 0B 97 10 E4 25 F7 EF C5 E6 07 75 4A 32 6C D8
01B0 | 52 58 ED F6 DB 10 0E 18 47 20 6F F6 EB E8 3C E8
01C0 | D2 44 A4 93 66 5E D5 5D 58 01 8D 43 29 3F 61 AB
01D0 | A2 50 7D 0E EE 9E 62 14 9E 23 DC 08 9E 3F 01 7C
01E0 | EE FF 39 A9 49 86 BA C8 EE C1 9D 0D AE 24 A3 A1
01F0 | 06 2F C4 BD E1 6A F8 CA CB 5C 12 AC CC F6 BB 1D
0200 | 12 4D 4E 9E A3 B9 67 46 C6 01 28 B5 66 92 F1 16
0210 | 9E D7 74 1B 15 4E CD 68 40 1D 5E D9 66 8F DE 8C
0220 | E1 FE 65 6F EC D8 C3 ED F4 AF D2 9C E2 CE E6 E0
0230 | 8A 63 64 67

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 3307FACD893759111C45C73611C652D3 Value generated by client in Step 1
server_nonce 20, 16 211141411C35332CB8E05DA1A9E70944 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 FE00010068655C507A7B28EDEFD23CBA B33292A68F753AACC95AA74E1D035C1D 31F400424F82B81775FB9D31C34B89D3 C74BD411D0810F552F2CF053A956DD44 50FFFFACFB3A26AE8A23FF0492A8E34C DD8CEDA402CFA72435801BCFD534FB49 C9C0326EFD7D5D0C727B8EFC8D7B7113 2AF16B0BF40B9710E425F7EFC5E60775 4A326CD85258EDF6DB100E1847206FF6 EBE83CE8D244A493665ED55D58018D43 293F61ABA2507D0EEE9E62149E23DC08 9E3F017CEEFF39A94986BAC8EEC19D0D AE24A3A1062FC4BDE16AF8CACB5C12AC CCF6BB1D124D4E9EA3B96746C60128B5 6692F1169ED7741B154ECD68401D5ED9 668FDE8CE1FE656FECD8C3EDF4AFD29C
E2CEE6E0
g_a diffie-hellman parameter
server_time 560, 4 8A636467 (1734632330 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 = 7148DF4C58C3036A4F45053C035B190227BA059BAF5F7B8F149B8A00AE58338C0B9ADE0A3662D94755E38C7C4BC556FD0AD07B3B0133D66F16161FAC105F67CE5AD512D122B8A0D3E9F83D136CD56129B1580D049A82FFCA5E59C591FE98359E8213FE4D8CE2836338EFDDC5E25EF6F9AFBCBF9F5C1EB621DCDFC7C00C90E1815A599B2B0ADC488BC1300D77A7F090785B091E08A32E82A2D8859D82759B1981E2AF573F8C6792BFB2BFA14064A89AB1FFD50D2D31B35E1BD08D10D3B77F936445607FCD49D9FD37039966294396D46BF72F5E661CEC2990FC50CC5A08589DFFD667806184100CF4AEDEFB129C0658A127570058D14F2234568AB8C57F5450E4

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

g_b = 74EA161BFB895E738A8D428424A9C9AFB8520D87EA21D130EECE5D1B71F064FEEE8F6D91466140B9EA832356C0C16F16236CD503602A9729D5E77BD43E99855F18CCFB7EAF2CFAE74728DD9CEDF4089AF77EFDA931D500E13E26E89E68027A417E87946A2DD4ABE60B70735C21AF9ABEB877BDD4955BF8CEBF1E275B9D5A001BA11DF356B0F562F9066AFC28F5AE750E19EA8004658BA1F5F894C362920BD873A9D764F2B09DB515EB1100CBED776DC30221BFF4C2FBA37EF0732A23DD3A92055C47573431F0E202D2267336C829935C64DD735B2B76CDAAE90695DED7918B7F134CCF27A1EFF3C7B50C19B1AEA15E7D0734A674D7A22CAD1EA29A8E98C057E3
7.1) generation of encrypted_data

Generated payload (excluding transport headers/trailers):

0000 | 54 B6 43 66 33 07 FA CD 89 37 59 11 1C 45 C7 36
0010 | 11 C6 52 D3 21 11 41 41 1C 35 33 2C B8 E0 5D A1
0020 | A9 E7 09 44 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | 74 EA 16 1B FB 89 5E 73 8A 8D 42 84 24 A9 C9 AF
0040 | B8 52 0D 87 EA 21 D1 30 EE CE 5D 1B 71 F0 64 FE
0050 | EE 8F 6D 91 46 61 40 B9 EA 83 23 56 C0 C1 6F 16
0060 | 23 6C D5 03 60 2A 97 29 D5 E7 7B D4 3E 99 85 5F
0070 | 18 CC FB 7E AF 2C FA E7 47 28 DD 9C ED F4 08 9A
0080 | F7 7E FD A9 31 D5 00 E1 3E 26 E8 9E 68 02 7A 41
0090 | 7E 87 94 6A 2D D4 AB E6 0B 70 73 5C 21 AF 9A BE
00A0 | B8 77 BD D4 95 5B F8 CE BF 1E 27 5B 9D 5A 00 1B
00B0 | A1 1D F3 56 B0 F5 62 F9 06 6A FC 28 F5 AE 75 0E
00C0 | 19 EA 80 04 65 8B A1 F5 F8 94 C3 62 92 0B D8 73
00D0 | A9 D7 64 F2 B0 9D B5 15 EB 11 00 CB ED 77 6D C3
00E0 | 02 21 BF F4 C2 FB A3 7E F0 73 2A 23 DD 3A 92 05
00F0 | 5C 47 57 34 31 F0 E2 02 D2 26 73 36 C8 29 93 5C
0100 | 64 DD 73 5B 2B 76 CD AA E9 06 95 DE D7 91 8B 7F
0110 | 13 4C CF 27 A1 EF F3 C7 B5 0C 19 B1 AE A1 5E 7D
0120 | 07 34 A6 74 D7 A2 2C AD 1E A2 9A 8E 98 C0 57 E3

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 3307FACD893759111C45C73611C652D3 Value generated by client in Step 1
server_nonce 20, 16 211141411C35332CB8E05DA1A9E70944 Value received from server in Step 2
g_b 36, 260 FE00010074EA161BFB895E738A8D4284 24A9C9AFB8520D87EA21D130EECE5D1B 71F064FEEE8F6D91466140B9EA832356 C0C16F16236CD503602A9729D5E77BD4 3E99855F18CCFB7EAF2CFAE74728DD9C EDF4089AF77EFDA931D500E13E26E89E 68027A417E87946A2DD4ABE60B70735C 21AF9ABEB877BDD4955BF8CEBF1E275B 9D5A001BA11DF356B0F562F9066AFC28 F5AE750E19EA8004658BA1F5F894C362 920BD873A9D764F2B09DB515EB1100CB ED776DC30221BFF4C2FBA37EF0732A23 DD3A92055C47573431F0E202D2267336 C829935C64DD735B2B76CDAAE90695DE D7918B7F134CCF27A1EFF3C7B50C19B1 AEA15E7D0734A674D7A22CAD1EA29A8E
98C057E3
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 = 54B643663307FACD893759111C45C73611C652D3211141411C35332CB8E05DA1A9E709440000000000000000FE00010074EA161BFB895E738A8D428424A9C9AFB8520D87EA21D130EECE5D1B71F064FEEE8F6D91466140B9EA832356C0C16F16236CD503602A9729D5E77BD43E99855F18CCFB7EAF2CFAE74728DD9CEDF4089AF77EFDA931D500E13E26E89E68027A417E87946A2DD4ABE60B70735C21AF9ABEB877BDD4955BF8CEBF1E275B9D5A001BA11DF356B0F562F9066AFC28F5AE750E19EA8004658BA1F5F894C362920BD873A9D764F2B09DB515EB1100CBED776DC30221BFF4C2FBA37EF0732A23DD3A92055C47573431F0E202D2267336C829935C64DD735B2B76CDAAE90695DED7918B7F134CCF27A1EFF3C7B50C19B1AEA15E7D0734A674D7A22CAD1EA29A8E98C057E3
padding = E4C6B7E9FF629BAD73C4E01D
tmp_aes_key = 0795629A5D2239A3C7D6621F456F374BBD159029604769225852B522FF4022D0
tmp_aes_iv = D36212548C7DA3DE584E6019C796C74F44C700A45123F014532F979D4BCABA6D

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 = 4EA2EE46F9AC9D7A2E79F2AD035AEFD0A775931D8C9B096A76CC83C78B059B07E2C6530BC5FF3B15EC434841F0C2196542F7ACF638F19DB9C72732E13DD940D4C6DE987B8E432CDD522CC076D73B935DC9188C6C81CC25E9203C2CF3BE9AE39C33C73823744D4A3E1E710D345668CAEA89F4D9D1397EE4FAA8AE1758D726D8FAB54D959BB7A45D536B8C66807770824866C724CF43F54A5C5CA87929DBC23BFFBE3F8879AF5B49288ACF06B0DB00095205E419FB64CF5C7BCF199DD22EA8DA21403DD566F02158B03D31272F9FF35104550444442E4C8B5C865B9C9BD6F313018EA0E6D3231E16D679B57FCDF80D84796B3777769B9B3668DD964BCB92226FA910BFBA30804B39851930FD1FF285FE54E2C316A57121ABE951CF40A7F92004737CFDBE4DDCB33073377FBC9F65536607C977AE2CE80B0EFED396B4E6F45F7F55309EE6BFA84C9C1A7A72CC9E2E022CE9

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 24 03 0F 00 8A 63 64 67
0010 | 78 01 00 00 1F 5F 04 F5 33 07 FA CD 89 37 59 11
0020 | 1C 45 C7 36 11 C6 52 D3 21 11 41 41 1C 35 33 2C
0030 | B8 E0 5D A1 A9 E7 09 44 FE 50 01 00 4E A2 EE 46
0040 | F9 AC 9D 7A 2E 79 F2 AD 03 5A EF D0 A7 75 93 1D
0050 | 8C 9B 09 6A 76 CC 83 C7 8B 05 9B 07 E2 C6 53 0B
0060 | C5 FF 3B 15 EC 43 48 41 F0 C2 19 65 42 F7 AC F6
0070 | 38 F1 9D B9 C7 27 32 E1 3D D9 40 D4 C6 DE 98 7B
0080 | 8E 43 2C DD 52 2C C0 76 D7 3B 93 5D C9 18 8C 6C
0090 | 81 CC 25 E9 20 3C 2C F3 BE 9A E3 9C 33 C7 38 23
00A0 | 74 4D 4A 3E 1E 71 0D 34 56 68 CA EA 89 F4 D9 D1
00B0 | 39 7E E4 FA A8 AE 17 58 D7 26 D8 FA B5 4D 95 9B
00C0 | B7 A4 5D 53 6B 8C 66 80 77 70 82 48 66 C7 24 CF
00D0 | 43 F5 4A 5C 5C A8 79 29 DB C2 3B FF BE 3F 88 79
00E0 | AF 5B 49 28 8A CF 06 B0 DB 00 09 52 05 E4 19 FB
00F0 | 64 CF 5C 7B CF 19 9D D2 2E A8 DA 21 40 3D D5 66
0100 | F0 21 58 B0 3D 31 27 2F 9F F3 51 04 55 04 44 44
0110 | 2E 4C 8B 5C 86 5B 9C 9B D6 F3 13 01 8E A0 E6 D3
0120 | 23 1E 16 D6 79 B5 7F CD F8 0D 84 79 6B 37 77 76
0130 | 9B 9B 36 68 DD 96 4B CB 92 22 6F A9 10 BF BA 30
0140 | 80 4B 39 85 19 30 FD 1F F2 85 FE 54 E2 C3 16 A5
0150 | 71 21 AB E9 51 CF 40 A7 F9 20 04 73 7C FD BE 4D
0160 | DC B3 30 73 37 7F BC 9F 65 53 66 07 C9 77 AE 2C
0170 | E8 0B 0E FE D3 96 B4 E6 F4 5F 7F 55 30 9E E6 BF
0180 | A8 4C 9C 1A 7A 72 CC 9E 2E 02 2C E9

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 24030F008A636467 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 3307FACD893759111C45C73611C652D3 Value generated by client in Step 1
server_nonce 40, 16 211141411C35332CB8E05DA1A9E70944 Value received from server in Step 2
encrypted_data 56, 340 FE5001004EA2EE46F9AC9D7A2E79F2AD 035AEFD0A775931D8C9B096A76CC83C7 8B059B07E2C6530BC5FF3B15EC434841 F0C2196542F7ACF638F19DB9C72732E1 3DD940D4C6DE987B8E432CDD522CC076 D73B935DC9188C6C81CC25E9203C2CF3 BE9AE39C33C73823744D4A3E1E710D34 5668CAEA89F4D9D1397EE4FAA8AE1758 D726D8FAB54D959BB7A45D536B8C6680 7770824866C724CF43F54A5C5CA87929 DBC23BFFBE3F8879AF5B49288ACF06B0 DB00095205E419FB64CF5C7BCF199DD2 2EA8DA21403DD566F02158B03D31272F 9FF35104550444442E4C8B5C865B9C9B D6F313018EA0E6D3231E16D679B57FCD F80D84796B3777769B9B3668DD964BCB 92226FA910BFBA30804B39851930FD1F F285FE54E2C316A57121ABE951CF40A7 F92004737CFDBE4DDCB33073377FBC9F 65536607C977AE2CE80B0EFED396B4E6 F45F7F55309EE6BFA84C9C1A7A72CC9E
2E022CE9
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 = A1CC4C5EC4C45B1FA14D915C88F50DFE224C88CF0B9863CCF0865FAD934B3669808F2EEEF6BB2B2D7607E553411065EE9DBD2D1FF5D0830845E3D941CC3F19D9176BF23ECE8A9031746BB6DCBEB51E4FED5027D1A8C2B36EA3FE9E4C8E356A719463C06E52D68D7253F23672AE1B41B086620502B1F427AAFFBE105AC8A2050211A294E134396D9BBE8A8A4C16CF37AB59361963683313108E3070C0BEB30A9F5D8167D43E16E8636A04D51AE7F4EA9AA95FEDC0D65A3E6B8100211C56C4E9151A013E0F84D1FA47875DAEF5DADA8447585651AE7C0C6BAF237492FFD7237F23DE0ECC48E64D2F04BA939D7F5E8443D428AEC93D594DE08729CCB0E6008DD75B
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 AC EB 46 8C 63 64 67
0010 | 34 00 00 00 34 F7 CB 3B 33 07 FA CD 89 37 59 11
0020 | 1C 45 C7 36 11 C6 52 D3 21 11 41 41 1C 35 33 2C
0030 | B8 E0 5D A1 A9 E7 09 44 F1 5B CD 97 04 41 B4 B2
0040 | E9 A8 C4 10 3A 4B 90 F1

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 01ACEB468C636467 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 3307FACD893759111C45C73611C652D3 Value generated by client in Step 1
server_nonce 40, 16 211141411C35332CB8E05DA1A9E70944 Value received from server in Step 2
new_nonce_hash1 56, 16 F15BCD970441B4B2E9A8C4103A4B90F1 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.