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 74 FE 09 00 A5 76 42 6A
0010 | 14 00 00 00 F1 8E 7E BE 7A 85 B8 E2 13 B2 DD BB
0020 | 21 68 85 19 D4 DC FD 57

Payload (de)serialization:

req_pq_multi#00000000 nonce:int128 = ResPQ;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 74FE0900A576426A 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 7A85B8E213B2DDBB21688519D4DCFD57 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 A4 61 E2 A5 76 42 6A
0010 | 50 00 00 00 63 24 16 05 7A 85 B8 E2 13 B2 DD BB
0020 | 21 68 85 19 D4 DC FD 57 12 92 3F 9A 3D 0F 00 CF
0030 | 2F 2B 96 C7 55 6A 7F 1C 08 25 C2 C7 48 EC A0 22
0040 | E1 00 00 00 15 C4 B5 1C 03 00 00 00 85 FD 64 DE
0050 | 85 1D 9D D0 A5 B7 F7 09 35 5F C3 0B 21 6B E8 6C
0060 | 02 2B B4 C3

Payload (de)serialization:

resPQ#00000000 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector<strlong> = ResPQ;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 01A461E2A576426A 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 7A85B8E213B2DDBB21688519D4DCFD57 Value generated by client in Step 1
server_nonce 40, 16 12923F9A3D0F00CF2F2B96C7556A7F1C Server-generated random number
pq 56, 12 0825C2C748ECA022E1000000
TL byte deserialization
=> bigendian conversion to decimal
=> 2720956240906691297
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 = 2720956240906691297

Decompose into 2 prime cofactors p < q: 2720956240906691297 = 1487202733 * 1829579909

p = 1487202733
q = 1829579909

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 25 C2 C7 48 EC A0 22 E1 00 00 00
0010 | 04 58 A4 E9 AD 00 00 00 04 6D 0D 2C 85 00 00 00
0020 | 7A 85 B8 E2 13 B2 DD BB 21 68 85 19 D4 DC FD 57
0030 | 12 92 3F 9A 3D 0F 00 CF 2F 2B 96 C7 55 6A 7F 1C
0040 | 89 7F D7 EE 23 5D 5E AC 74 86 3A 73 B4 12 39 4E
0050 | 32 DF 7D 98 28 B2 4E 3A A9 F6 71 B6 32 A4 19 E9
0060 | 02 00 00 00

Payload (de)serialization:

p_q_inner_data_dc#00000000 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data;
Parameter Offset, Length in bytes Value Description
%(p_q_inner_data_dc) 0, 4 955ff5a9 p_q_inner_data_dc constructor number from TL schema
pq 4, 12 0825C2C748ECA022E1000000
TL byte deserialization
=> bigendian conversion to decimal
=> 2720956240906691297
Single-byte prefix denoting length, 8-byte string, and three bytes of padding
p 16, 8 0458A4E9AD000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1487202733
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 24, 8 046D0D2C85000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1829579909
Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
nonce 32, 16 7A85B8E213B2DDBB21688519D4DCFD57 Value generated by client in Step 1
server_nonce 48, 16 12923F9A3D0F00CF2F2B96C7556A7F1C Value received from server in Step 2
new_nonce 64, 32 897FD7EE235D5EAC74863A73B412394E 32DF7D9828B24E3AA9F671B632A419E9 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 = 955FF5A90825C2C748ECA022E10000000458A4E9AD000000046D0D2C850000007A85B8E213B2DDBB21688519D4DCFD5712923F9A3D0F00CF2F2B96C7556A7F1C897FD7EE235D5EAC74863A73B412394E32DF7D9828B24E3AA9F671B632A419E902000000
random_padding_bytes = 3A32BC307BF75ABD3DA7D976AE390197F833C5211801BAF4DE7CE9E3F46787B30E81F7948114944AA6D534E66E45C88980E6E406E6CE206BD99E1A55455B2927E3D15F3AC56E4DF4A69FDD9B1B8A43966265DD4C4BCB8972DAABC4DE

And this is the output:

encrypted_data = 6F2D259C0C7FF599705D6C195674EF6D4F2ABEE825903F44B9F5B1D514A22D8994E5262DE52E0F5EDD074C15AE23A5D58DC4198EC951D51043A9F7B8267599301FD02793C7C4BC2B0B98E54ACB2FD59B3FCDF246DDA5CED2768953D1F552D7500FC439EB47D7AE4F6D28D1A0EB9CBBFDDD860303C11C53FDC35D2E1E78D048F6ABF0378E05688DC139CC2EE0FCA335FE4369E69F3023A179FC7607C0EBC060CF9E6F43355F489C4FDF58FC1D7564FC196EDBDC86FE5DF5430AB44BA5779BCB3A33B5636706D0E35389479D53A0D433C2B4030A4E2F0E5910336ACB59E08017DB5FB15FC7C953D967D663245A3E6F2CED3C3FDAD90326BE82B96D7F3FFAD5D44C

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 78 FE 09 00 A5 76 42 6A
0010 | 40 01 00 00 BE E4 12 D7 7A 85 B8 E2 13 B2 DD BB
0020 | 21 68 85 19 D4 DC FD 57 12 92 3F 9A 3D 0F 00 CF
0030 | 2F 2B 96 C7 55 6A 7F 1C 04 58 A4 E9 AD 00 00 00
0040 | 04 6D 0D 2C 85 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 6F 2D 25 9C 0C 7F F5 99 70 5D 6C 19
0060 | 56 74 EF 6D 4F 2A BE E8 25 90 3F 44 B9 F5 B1 D5
0070 | 14 A2 2D 89 94 E5 26 2D E5 2E 0F 5E DD 07 4C 15
0080 | AE 23 A5 D5 8D C4 19 8E C9 51 D5 10 43 A9 F7 B8
0090 | 26 75 99 30 1F D0 27 93 C7 C4 BC 2B 0B 98 E5 4A
00A0 | CB 2F D5 9B 3F CD F2 46 DD A5 CE D2 76 89 53 D1
00B0 | F5 52 D7 50 0F C4 39 EB 47 D7 AE 4F 6D 28 D1 A0
00C0 | EB 9C BB FD DD 86 03 03 C1 1C 53 FD C3 5D 2E 1E
00D0 | 78 D0 48 F6 AB F0 37 8E 05 68 8D C1 39 CC 2E E0
00E0 | FC A3 35 FE 43 69 E6 9F 30 23 A1 79 FC 76 07 C0
00F0 | EB C0 60 CF 9E 6F 43 35 5F 48 9C 4F DF 58 FC 1D
0100 | 75 64 FC 19 6E DB DC 86 FE 5D F5 43 0A B4 4B A5
0110 | 77 9B CB 3A 33 B5 63 67 06 D0 E3 53 89 47 9D 53
0120 | A0 D4 33 C2 B4 03 0A 4E 2F 0E 59 10 33 6A CB 59
0130 | E0 80 17 DB 5F B1 5F C7 C9 53 D9 67 D6 63 24 5A
0140 | 3E 6F 2C ED 3C 3F DA D9 03 26 BE 82 B9 6D 7F 3F
0150 | FA D5 D4 4C

Payload (de)serialization:

req_DH_params#00000000 nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 78FE0900A576426A 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 7A85B8E213B2DDBB21688519D4DCFD57 Value generated by client in Step 1
server_nonce 40, 16 12923F9A3D0F00CF2F2B96C7556A7F1C Value received from server in Step 2
p 56, 8 0458A4E9AD000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1487202733
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding
q 64, 8 046D0D2C85000000
TL byte deserialization
=> bigendian conversion to decimal
=> 1829579909
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 FE0001006F2D259C0C7FF599705D6C19 5674EF6D4F2ABEE825903F44B9F5B1D5 14A22D8994E5262DE52E0F5EDD074C15 AE23A5D58DC4198EC951D51043A9F7B8 267599301FD02793C7C4BC2B0B98E54A CB2FD59B3FCDF246DDA5CED2768953D1 F552D7500FC439EB47D7AE4F6D28D1A0 EB9CBBFDDD860303C11C53FDC35D2E1E 78D048F6ABF0378E05688DC139CC2EE0 FCA335FE4369E69F3023A179FC7607C0 EBC060CF9E6F43355F489C4FDF58FC1D 7564FC196EDBDC86FE5DF5430AB44BA5 779BCB3A33B5636706D0E35389479D53 A0D433C2B4030A4E2F0E5910336ACB59 E08017DB5FB15FC7C953D967D663245A 3E6F2CED3C3FDAD90326BE82B96D7F3F
FAD5D44C
Value generated above
6) Server responds with:

Received payload (excluding transport headers/trailers):

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

Payload (de)serialization:

server_DH_params_ok#00000000 nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 01E03E27A676426A 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 7A85B8E213B2DDBB21688519D4DCFD57 Value generated by client in Step 1
server_nonce 40, 16 12923F9A3D0F00CF2F2B96C7556A7F1C Value received from server in Step 2
encrypted_answer 56, 596 FE50020092F1645584455559B3D6F706 3382E4014BA7065C22285A6DF8800804 287AC3BE57B017087DB7DBC6D2FA9E7D 5D5E587586B133A78A87A3170ADC7DD9 62048ED0D6FC0C4C95E36BBA5BF2409B 3D140FE2D9A0FE54EAE5CA4A6881F2C2 E58ADEF753B3990750842C069E182FA2 A9D9D0CCDF01FF420D2A8056BF807131 1FAF6B87C4806A831551053F871767D2 3DB3B55C70F773AC809836FE505D60EE 3431108097CC43BA2EABA3D8CDA85EF0 45881853BB135E17D5F74466C9126FBD 34D7EF2B776D46FAC121E12E13DFECAB 1A34BE765A52208B3D2B999541DA3AAC 19D4B1E488CCBD3CA8DDEBB9E3E93218 5533DD9970687417CFD7E1650EE91C82 D4763C74591E6877BAED2C7112650C4A 7633CB56A98534C795E92CBFBCECC143 B8239150FC67C52E82352E9205ACBA4C 9B83DD69E22DBE16D5B50E86C74CECC4 9C4786A6242D3F1898B4AE5B20295A7C C27511372C48524B6AB94A0917AE0101 CB49D0B249381129DB42ADCA1F69A5A1 119452B0E7C7CA2E7E0CEEC4A8C97ED7 37B6313A971ED00EB43056B60F6678A4 4F5F8F20F6A26BAFDCDD93BA838C9224 14D34ADB2060AF99A08752F3997E4A70 69E6572EE04753986C21A0E18758DECB 90C02AEDC292928D5DA0F04ACDAE09D6 536E1A4C6797B740918412F43E4B1AF8 1888F5D813C9E8631A79BAA18DCD6F52 20E3C606873DD3C17D6A13F7296777BA 99EB214AE6AA69913A94B44149C07FC6 BBD9A87E6909BC89926F1BCFDBE034B4 E43494BBBF05F5689EF7FCB0C855F653 E541277BCCB59C0D75749CACC60302AC 1EC40BE45BDD8F0B77F1A15C61D37468
9D5CF989
See below

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

encrypted_answer = 92F1645584455559B3D6F7063382E4014BA7065C22285A6DF8800804287AC3BE57B017087DB7DBC6D2FA9E7D5D5E587586B133A78A87A3170ADC7DD962048ED0D6FC0C4C95E36BBA5BF2409B3D140FE2D9A0FE54EAE5CA4A6881F2C2E58ADEF753B3990750842C069E182FA2A9D9D0CCDF01FF420D2A8056BF8071311FAF6B87C4806A831551053F871767D23DB3B55C70F773AC809836FE505D60EE3431108097CC43BA2EABA3D8CDA85EF045881853BB135E17D5F74466C9126FBD34D7EF2B776D46FAC121E12E13DFECAB1A34BE765A52208B3D2B999541DA3AAC19D4B1E488CCBD3CA8DDEBB9E3E932185533DD9970687417CFD7E1650EE91C82D4763C74591E6877BAED2C7112650C4A7633CB56A98534C795E92CBFBCECC143B8239150FC67C52E82352E9205ACBA4C9B83DD69E22DBE16D5B50E86C74CECC49C4786A6242D3F1898B4AE5B20295A7CC27511372C48524B6AB94A0917AE0101CB49D0B249381129DB42ADCA1F69A5A1119452B0E7C7CA2E7E0CEEC4A8C97ED737B6313A971ED00EB43056B60F6678A44F5F8F20F6A26BAFDCDD93BA838C922414D34ADB2060AF99A08752F3997E4A7069E6572EE04753986C21A0E18758DECB90C02AEDC292928D5DA0F04ACDAE09D6536E1A4C6797B740918412F43E4B1AF81888F5D813C9E8631A79BAA18DCD6F5220E3C606873DD3C17D6A13F7296777BA99EB214AE6AA69913A94B44149C07FC6BBD9A87E6909BC89926F1BCFDBE034B4E43494BBBF05F5689EF7FCB0C855F653E541277BCCB59C0D75749CACC60302AC1EC40BE45BDD8F0B77F1A15C61D374689D5CF989
tmp_aes_key = 52421310325A031F2DE67C0D4915516112C47E730C4D4FB8D7CCA7E68BE3887D
tmp_aes_iv = AA5E08E9E35C4B500509C7D4964D398A86B9EF57E3F890D8B6E6E635897FD7EE

Yielding:

answer_with_hash = E97EE77884488743D37824BF7C03C74DEF3D7D26BA0D89B57A85B8E213B2DDBB21688519D4DCFD5712923F9A3D0F00CF2F2B96C7556A7F1C03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001004C74D57A161861D67C3783D39E07E7296C8BE28D0C029982168E1609B0F437EF541D30B05FAE23C6C83A45DA56F7C5A4B6D4F48E954EC8104E8B1D90046AE687DB76450A72410236809FC0D3E13ABCC4B66B60D8C24BCEA5D138C4689C7AC3E3CF01A1B6F8E086A983C374442E7B8EC4F483A9C7D5CB19B36421A4374BE1483AA66BB549BB1D5E5DFE0213F1999250B2785D42CCF2593635BF7FA84D705BE91871D6258E3E58035657D856D6587D38B217EF73ACD5B1E634882852B558AF9D9258B736A2B1A023D056B14F44D6B94B25815EFC791C5198FB576D7D2075A915EF4EEFFFE41C72B1DB4C7B72846861E66D601A19F2DFD090C661C6F2249CA4FB23A676426A3785A9167AF5FE92
answer = BA0D89B57A85B8E213B2DDBB21688519D4DCFD5712923F9A3D0F00CF2F2B96C7556A7F1C03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001004C74D57A161861D67C3783D39E07E7296C8BE28D0C029982168E1609B0F437EF541D30B05FAE23C6C83A45DA56F7C5A4B6D4F48E954EC8104E8B1D90046AE687DB76450A72410236809FC0D3E13ABCC4B66B60D8C24BCEA5D138C4689C7AC3E3CF01A1B6F8E086A983C374442E7B8EC4F483A9C7D5CB19B36421A4374BE1483AA66BB549BB1D5E5DFE0213F1999250B2785D42CCF2593635BF7FA84D705BE91871D6258E3E58035657D856D6587D38B217EF73ACD5B1E634882852B558AF9D9258B736A2B1A023D056B14F44D6B94B25815EFC791C5198FB576D7D2075A915EF4EEFFFE41C72B1DB4C7B72846861E66D601A19F2DFD090C661C6F2249CA4FB23A676426A3785A9167AF5FE92

Generated payload (excluding transport headers/trailers):

0000 | BA 0D 89 B5 7A 85 B8 E2 13 B2 DD BB 21 68 85 19
0010 | D4 DC FD 57 12 92 3F 9A 3D 0F 00 CF 2F 2B 96 C7
0020 | 55 6A 7F 1C 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 | 4C 74 D5 7A 16 18 61 D6 7C 37 83 D3 9E 07 E7 29
0140 | 6C 8B E2 8D 0C 02 99 82 16 8E 16 09 B0 F4 37 EF
0150 | 54 1D 30 B0 5F AE 23 C6 C8 3A 45 DA 56 F7 C5 A4
0160 | B6 D4 F4 8E 95 4E C8 10 4E 8B 1D 90 04 6A E6 87
0170 | DB 76 45 0A 72 41 02 36 80 9F C0 D3 E1 3A BC C4
0180 | B6 6B 60 D8 C2 4B CE A5 D1 38 C4 68 9C 7A C3 E3
0190 | CF 01 A1 B6 F8 E0 86 A9 83 C3 74 44 2E 7B 8E C4
01A0 | F4 83 A9 C7 D5 CB 19 B3 64 21 A4 37 4B E1 48 3A
01B0 | A6 6B B5 49 BB 1D 5E 5D FE 02 13 F1 99 92 50 B2
01C0 | 78 5D 42 CC F2 59 36 35 BF 7F A8 4D 70 5B E9 18
01D0 | 71 D6 25 8E 3E 58 03 56 57 D8 56 D6 58 7D 38 B2
01E0 | 17 EF 73 AC D5 B1 E6 34 88 28 52 B5 58 AF 9D 92
01F0 | 58 B7 36 A2 B1 A0 23 D0 56 B1 4F 44 D6 B9 4B 25
0200 | 81 5E FC 79 1C 51 98 FB 57 6D 7D 20 75 A9 15 EF
0210 | 4E EF FF E4 1C 72 B1 DB 4C 7B 72 84 68 61 E6 6D
0220 | 60 1A 19 F2 DF D0 90 C6 61 C6 F2 24 9C A4 FB 23
0230 | A6 76 42 6A

Payload (de)serialization:

server_DH_inner_data#00000000 nonce:int128 server_nonce:int128 g:int dh_prime:string g_a:string server_time:int = Server_DH_inner_data;
Parameter Offset, Length in bytes Value Description
%(server_DH_inner_data) 0, 4 ba0d89b5 server_DH_inner_data constructor number from TL schema
nonce 4, 16 7A85B8E213B2DDBB21688519D4DCFD57 Value generated by client in Step 1
server_nonce 20, 16 12923F9A3D0F00CF2F2B96C7556A7F1C 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 FE0001004C74D57A161861D67C3783D3 9E07E7296C8BE28D0C029982168E1609 B0F437EF541D30B05FAE23C6C83A45DA 56F7C5A4B6D4F48E954EC8104E8B1D90 046AE687DB76450A72410236809FC0D3 E13ABCC4B66B60D8C24BCEA5D138C468 9C7AC3E3CF01A1B6F8E086A983C37444 2E7B8EC4F483A9C7D5CB19B36421A437 4BE1483AA66BB549BB1D5E5DFE0213F1 999250B2785D42CCF2593635BF7FA84D 705BE91871D6258E3E58035657D856D6 587D38B217EF73ACD5B1E634882852B5 58AF9D9258B736A2B1A023D056B14F44 D6B94B25815EFC791C5198FB576D7D20 75A915EF4EEFFFE41C72B1DB4C7B7284 6861E66D601A19F2DFD090C661C6F224
9CA4FB23
g_a diffie-hellman parameter
server_time 560, 4 A676426A (1782740646 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 = 4E7680EA689C563086DD53C26D377D9F0A9EEE7C596B502A7D79C34C683C64F3B390C641B84E7CA06DC7B4AD7272E9CD45E97F973F89BB75866A1A878083901FFAF6917CBFB034E4298E2F94D5908B66E643D1883D09E89FB926354732AEBDB36CDE9A0844049E2BAD6AF67CFAC0FF63C5CDCD6AE15039CC23C87907E774E4D606A9F46D56906462E91918BC45A83CA4616B7D72F84E9F782482B658692BC7FF5A23543DB508E905D74D5F793286ECFA90E74E5C6DF2CDFA3763B8DE3E993DE05BC9C39BEEAF359DEDCC1D98C3B5CE82385CD687219B429C12CDDE800B76DE156F19B2DE98C807C4DED514CC6A8F592339DB0BFCD2B7B32A2AE0A2A98A1822E5

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

g_b = AB6C4F34A08B8101F336B66783FE2A80F6B859C4687D86192AC36BE256AC53D8583E97386F3420419F4016CA3CCC38978CC2F9A7E65266847C745F80FD76802DD0167EF858CAFDAB910FBCD640ECD34A771F2BCC53A26E319D490380B1745E9A1A00EDB04B6EE2AD5DC3A925C5BBF5B47B2FF0A80FC03F811FAD2B223A445A47D0E635F0D30B9CF8BF307C111D5054D94D8AB43DCBA675E1EE446A11BBE4ED70A30AFAFFA62041BABA13C54F71F5E10AF1C8F1A7DE576372F94B48D19A5400B310ED1368A4C574FE018C7AB8D901FC22100FBCE565302D92315877940F6729DEE08EE9CF799AEE514A43B93612C03C0545EF68EBDB406CAC9411316D64B3BF56
7.1) generation of encrypted_data

Generated payload (excluding transport headers/trailers):

0000 | 54 B6 43 66 7A 85 B8 E2 13 B2 DD BB 21 68 85 19
0010 | D4 DC FD 57 12 92 3F 9A 3D 0F 00 CF 2F 2B 96 C7
0020 | 55 6A 7F 1C 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | AB 6C 4F 34 A0 8B 81 01 F3 36 B6 67 83 FE 2A 80
0040 | F6 B8 59 C4 68 7D 86 19 2A C3 6B E2 56 AC 53 D8
0050 | 58 3E 97 38 6F 34 20 41 9F 40 16 CA 3C CC 38 97
0060 | 8C C2 F9 A7 E6 52 66 84 7C 74 5F 80 FD 76 80 2D
0070 | D0 16 7E F8 58 CA FD AB 91 0F BC D6 40 EC D3 4A
0080 | 77 1F 2B CC 53 A2 6E 31 9D 49 03 80 B1 74 5E 9A
0090 | 1A 00 ED B0 4B 6E E2 AD 5D C3 A9 25 C5 BB F5 B4
00A0 | 7B 2F F0 A8 0F C0 3F 81 1F AD 2B 22 3A 44 5A 47
00B0 | D0 E6 35 F0 D3 0B 9C F8 BF 30 7C 11 1D 50 54 D9
00C0 | 4D 8A B4 3D CB A6 75 E1 EE 44 6A 11 BB E4 ED 70
00D0 | A3 0A FA FF A6 20 41 BA BA 13 C5 4F 71 F5 E1 0A
00E0 | F1 C8 F1 A7 DE 57 63 72 F9 4B 48 D1 9A 54 00 B3
00F0 | 10 ED 13 68 A4 C5 74 FE 01 8C 7A B8 D9 01 FC 22
0100 | 10 0F BC E5 65 30 2D 92 31 58 77 94 0F 67 29 DE
0110 | E0 8E E9 CF 79 9A EE 51 4A 43 B9 36 12 C0 3C 05
0120 | 45 EF 68 EB DB 40 6C AC 94 11 31 6D 64 B3 BF 56

Payload (de)serialization:

client_DH_inner_data#00000000 nonce:int128 server_nonce:int128 retry_id:long g_b:string = Client_DH_Inner_Data;
Parameter Offset, Length in bytes Value Description
%(client_DH_inner_data) 0, 4 54b64366 client_DH_inner_data constructor number from TL schema
nonce 4, 16 7A85B8E213B2DDBB21688519D4DCFD57 Value generated by client in Step 1
server_nonce 20, 16 12923F9A3D0F00CF2F2B96C7556A7F1C Value received from server in Step 2
g_b 36, 260 FE000100AB6C4F34A08B8101F336B667 83FE2A80F6B859C4687D86192AC36BE2 56AC53D8583E97386F3420419F4016CA 3CCC38978CC2F9A7E65266847C745F80 FD76802DD0167EF858CAFDAB910FBCD6 40ECD34A771F2BCC53A26E319D490380 B1745E9A1A00EDB04B6EE2AD5DC3A925 C5BBF5B47B2FF0A80FC03F811FAD2B22 3A445A47D0E635F0D30B9CF8BF307C11 1D5054D94D8AB43DCBA675E1EE446A11 BBE4ED70A30AFAFFA62041BABA13C54F 71F5E10AF1C8F1A7DE576372F94B48D1 9A5400B310ED1368A4C574FE018C7AB8 D901FC22100FBCE565302D9231587794 0F6729DEE08EE9CF799AEE514A43B936 12C03C0545EF68EBDB406CAC9411316D
64B3BF56
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 = 54B643667A85B8E213B2DDBB21688519D4DCFD5712923F9A3D0F00CF2F2B96C7556A7F1C0000000000000000FE000100AB6C4F34A08B8101F336B66783FE2A80F6B859C4687D86192AC36BE256AC53D8583E97386F3420419F4016CA3CCC38978CC2F9A7E65266847C745F80FD76802DD0167EF858CAFDAB910FBCD640ECD34A771F2BCC53A26E319D490380B1745E9A1A00EDB04B6EE2AD5DC3A925C5BBF5B47B2FF0A80FC03F811FAD2B223A445A47D0E635F0D30B9CF8BF307C111D5054D94D8AB43DCBA675E1EE446A11BBE4ED70A30AFAFFA62041BABA13C54F71F5E10AF1C8F1A7DE576372F94B48D19A5400B310ED1368A4C574FE018C7AB8D901FC22100FBCE565302D92315877940F6729DEE08EE9CF799AEE514A43B93612C03C0545EF68EBDB406CAC9411316D64B3BF56
padding = FDF526346BD1A6348DF5B586
tmp_aes_key = 52421310325A031F2DE67C0D4915516112C47E730C4D4FB8D7CCA7E68BE3887D
tmp_aes_iv = AA5E08E9E35C4B500509C7D4964D398A86B9EF57E3F890D8B6E6E635897FD7EE

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

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 04 47 01 00 A6 76 42 6A
0010 | 78 01 00 00 1F 5F 04 F5 7A 85 B8 E2 13 B2 DD BB
0020 | 21 68 85 19 D4 DC FD 57 12 92 3F 9A 3D 0F 00 CF
0030 | 2F 2B 96 C7 55 6A 7F 1C FE 50 01 00 BF 16 3A DA
0040 | 85 20 95 04 E9 8D C0 64 98 3B AC 3E 0D 25 A5 44
0050 | D7 BD 4C DB E8 CF 10 2B 49 41 50 AC 39 61 1C F0
0060 | 84 5B 9B 68 77 4C B8 72 5C 8D B0 D5 21 EB 0F 60
0070 | 73 C8 11 39 A2 DD 93 10 82 72 72 84 21 EB 5A 7D
0080 | FE 4F 9B 03 59 FA 94 12 13 C7 70 9A B8 C0 31 6A
0090 | 88 49 6E 87 3A 48 12 C7 8B 87 89 3D 12 BE 5D D2
00A0 | B7 ED 1A 10 E3 77 13 5F 99 1E ED 84 ED 3F 05 E1
00B0 | CB B1 0C CA 67 F5 B0 A3 1F DB 84 67 D1 1D 0E F0
00C0 | BC 15 11 2A AF 90 DA 4E 8B 9E 12 71 4D 36 E5 39
00D0 | EF DB 00 5A 65 0C 3E 53 07 D7 FB 7D 8A B4 29 31
00E0 | 04 2A 1F 16 52 13 3B 41 F0 B3 86 DE FB 2D 13 D4
00F0 | 5C A3 97 E1 1D 89 62 DD F9 E6 64 37 2F 94 DB DF
0100 | FF D0 2C 39 4E 68 FD BD 00 E9 3E 4F 73 49 63 9A
0110 | 7E 29 DC FA ED 16 D2 A1 C6 AE 5E 17 F5 47 63 77
0120 | 29 D0 DA ED C1 16 10 98 3B E4 97 4B 74 0D DA 9E
0130 | EB 36 F2 89 AC E6 E1 14 3F D2 19 DD 07 7B DC D9
0140 | A8 02 DA F0 7A 90 AB 0A 62 0E 14 10 E0 F4 69 4F
0150 | 29 E2 E8 B1 E5 D1 CA 7B 42 21 17 D8 4F EE BB E5
0160 | F5 E4 69 47 C0 19 48 6A 52 1A DB E6 91 25 78 D6
0170 | A1 03 42 4C 9C 0D D8 2F D0 89 69 DA 1B 67 51 76
0180 | A2 D9 85 7F 6C EB C3 8E E1 19 C7 5F

Payload (de)serialization:

set_client_DH_params#00000000 nonce:int128 server_nonce:int128 encrypted_data:string = Set_client_DH_params_answer;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 04470100A676426A 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 7A85B8E213B2DDBB21688519D4DCFD57 Value generated by client in Step 1
server_nonce 40, 16 12923F9A3D0F00CF2F2B96C7556A7F1C Value received from server in Step 2
encrypted_data 56, 340 FE500100BF163ADA85209504E98DC064 983BAC3E0D25A544D7BD4CDBE8CF102B 494150AC39611CF0845B9B68774CB872 5C8DB0D521EB0F6073C81139A2DD9310 8272728421EB5A7DFE4F9B0359FA9412 13C7709AB8C0316A88496E873A4812C7 8B87893D12BE5DD2B7ED1A10E377135F 991EED84ED3F05E1CBB10CCA67F5B0A3 1FDB8467D11D0EF0BC15112AAF90DA4E 8B9E12714D36E539EFDB005A650C3E53 07D7FB7D8AB42931042A1F1652133B41 F0B386DEFB2D13D45CA397E11D8962DD F9E664372F94DBDFFFD02C394E68FDBD 00E93E4F7349639A7E29DCFAED16D2A1 C6AE5E17F547637729D0DAEDC1161098 3BE4974B740DDA9EEB36F289ACE6E114 3FD219DD077BDCD9A802DAF07A90AB0A 620E1410E0F4694F29E2E8B1E5D1CA7B 422117D84FEEBBE5F5E46947C019486A 521ADBE6912578D6A103424C9C0DD82F D08969DA1B675176A2D9857F6CEBC38E
E119C75F
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 = 2D4F79E0051D99CF9C2AD8B78DAE5CBCDB54A6B3F686866D9FFFDCF38405C4A27343F101B086121C6BF81710C8311735D0F6EA18C4F39F0C4FE1865432294AD4D4CA44DAE881D2E4F6AC8E42CAFB4FFC6CEC3CDA2C45D686EED69BD8A62010E2BAECAB8A7538FDED56BA12CE20FA1E2F29879FAF43EF9884AB328B069585CBD54093C7C7FBC3731A5BF862EC7A3559230B5EB1D2C55C3CD1E44BA0C0831BF9A74947FAED71E83B22888106F5EDB944D062D1EA8200E1A8B81F4808D835EB538CC61AB6B7753552B0BF0360F9E91686CADE4AB9A7844A9D65A7BF08EBA9D795F56F0459450EFAD9F6844F4657C098B3759FB4570BE03CF7D70065EB3D066C8D51
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 F4 FC 37 A7 76 42 6A
0010 | 34 00 00 00 34 F7 CB 3B 7A 85 B8 E2 13 B2 DD BB
0020 | 21 68 85 19 D4 DC FD 57 12 92 3F 9A 3D 0F 00 CF
0030 | 2F 2B 96 C7 55 6A 7F 1C 10 17 63 7B 8D A3 9F 0C
0040 | D0 1A 73 89 6F B3 37 FE

Payload (de)serialization:

dh_gen_ok#00000004 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;
Parameter Offset, Length in bytes Value Description
auth_key_id 0, 8 0000000000000000 0 since the message is in plain text
message_id 8, 8 01F4FC37A776426A 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 7A85B8E213B2DDBB21688519D4DCFD57 Value generated by client in Step 1
server_nonce 40, 16 12923F9A3D0F00CF2F2B96C7556A7F1C Value received from server in Step 2
new_nonce_hash1 56, 16 1017637B8DA39F0CD01A73896FB337FE 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.