In the examples below, the transport headers are omitted:
For example, for the abridged version of the transport », the client sends
0xefas 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; or0x7ffollowed 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 send0xefas the first byte). Detailed documentation on creating authorization keys is available here ».
Sent payload (excluding transport headers/trailers):
0000 | 00 00 00 00 00 00 00 00 78 F4 04 00 61 70 46 6A
0010 | 14 00 00 00 F1 8E 7E BE 51 A1 14 3F C7 A3 66 6B
0020 | E4 BE 54 D6 89 0A 02 DC
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 | 78F404006170466A |
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 | 51A1143FC7A3666BE4BE54D6890A02DC |
Random number |
Received payload (excluding transport headers/trailers):
0000 | 00 00 00 00 00 00 00 00 01 F4 CC C2 61 70 46 6A
0010 | 50 00 00 00 63 24 16 05 51 A1 14 3F C7 A3 66 6B
0020 | E4 BE 54 D6 89 0A 02 DC 63 24 8F 67 48 21 4E AB
0030 | 8A 2F 4C C8 76 E1 19 74 08 2E 9C DB 98 C8 0C DA
0040 | 4B 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 | 01F4CCC26170466A |
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 | 51A1143FC7A3666BE4BE54D6890A02DC |
Value generated by client in Step 1 |
| server_nonce | 40, 16 | 63248F6748214EAB8A2F4CC876E11974 |
Server-generated random number |
| pq | 56, 12 | 082E9CDB98C80CDA4B000000TL byte deserialization => bigendian conversion to decimal => 3358800871349344843 |
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:
85FD64DE851D9DD0Let's choose the only matching key, the one with fingerprint equal to 85FD64DE851D9DD0.
pq = 3358800871349344843
Decompose into 2 prime cofactors p < q: 3358800871349344843 = 1786331737 * 1880278339
p = 1786331737
q = 1880278339
encrypted_data payload generationFirst of all, generate an encrypted_data payload as follows:
Generated payload (excluding transport headers/trailers):
0000 | 95 5F F5 A9 08 2E 9C DB 98 C8 0C DA 4B 00 00 00
0010 | 04 6A 79 42 59 00 00 00 04 70 12 C5 43 00 00 00
0020 | 51 A1 14 3F C7 A3 66 6B E4 BE 54 D6 89 0A 02 DC
0030 | 63 24 8F 67 48 21 4E AB 8A 2F 4C C8 76 E1 19 74
0040 | BF 8C B5 BD 9C 5B 4F E7 CF 24 D6 4D 28 1F 89 31
0050 | 15 76 D5 3C 0D A6 5A 83 26 7E 57 31 54 14 C9 A6
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 | 082E9CDB98C80CDA4B000000TL byte deserialization => bigendian conversion to decimal => 3358800871349344843 |
Single-byte prefix denoting length, 8-byte string, and three bytes of padding |
| p | 16, 8 | 046A794259000000TL byte deserialization => bigendian conversion to decimal => 1786331737 |
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding |
| q | 24, 8 | 047012C543000000TL byte deserialization => bigendian conversion to decimal => 1880278339 |
Second prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding |
| nonce | 32, 16 | 51A1143FC7A3666BE4BE54D6890A02DC |
Value generated by client in Step 1 |
| server_nonce | 48, 16 | 63248F6748214EAB8A2F4CC876E11974 |
Value received from server in Step 2 |
| new_nonce | 64, 32 | BF8CB5BD9C5B4FE7CF24D64D281F8931 1576D53C0DA65A83267E57315414C9A6 |
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 = 955FF5A9082E9CDB98C80CDA4B000000046A794259000000047012C54300000051A1143FC7A3666BE4BE54D6890A02DC63248F6748214EAB8A2F4CC876E11974BF8CB5BD9C5B4FE7CF24D64D281F89311576D53C0DA65A83267E57315414C9A602000000
random_padding_bytes = CAA2EE40A79783204C32BE8CB0EB37F550E2B037C8D587641F0AA0CC5A00ED9A482D035C8535ECC4E1D7FD961765525AD4E09497F9152C013CC14E9D50357A280F33E60E86AEF0B92775947BDF76D95966CCD0FF47E06FA6F2C8ACDF
And this is the output:
encrypted_data = 07FB235B4C7728558405705E3F18B09E5E2434977C42112E50DDE7C339D5893F966E40D8C951E37D9E32538189A83D59E005502B7CC125FBCD346EE75E33D0A26EDFFF456914245AC707B427E1DA7C7EAADBE1DD868B81B675D516E8DD20193FD51CACDE5A2281DCC57A724C77872511F7D156AAA032C7E731F971F3F4C9BE9233A3A1EE782C3311B0D380C0639386B57366AB38CA232B08805095D182C1382F1E0274D3EAE59F08AB7C8F50BB9CE75AB7A2B727A052F720B115BE65F455128B02BF182D243255894E1D376C4B287D45218012FBA1B9CD7619B1CF827FEAB4E00EB9722A126CC022A1DDCC094F3B7F258FDEE75FA21C8DA61F4136C23BADDB0C
The length of the final string is 256 bytes.
encrypted_dataSent payload (excluding transport headers/trailers):
0000 | 00 00 00 00 00 00 00 00 F4 DD 0B 00 61 70 46 6A
0010 | 40 01 00 00 BE E4 12 D7 51 A1 14 3F C7 A3 66 6B
0020 | E4 BE 54 D6 89 0A 02 DC 63 24 8F 67 48 21 4E AB
0030 | 8A 2F 4C C8 76 E1 19 74 04 6A 79 42 59 00 00 00
0040 | 04 70 12 C5 43 00 00 00 85 FD 64 DE 85 1D 9D D0
0050 | FE 00 01 00 07 FB 23 5B 4C 77 28 55 84 05 70 5E
0060 | 3F 18 B0 9E 5E 24 34 97 7C 42 11 2E 50 DD E7 C3
0070 | 39 D5 89 3F 96 6E 40 D8 C9 51 E3 7D 9E 32 53 81
0080 | 89 A8 3D 59 E0 05 50 2B 7C C1 25 FB CD 34 6E E7
0090 | 5E 33 D0 A2 6E DF FF 45 69 14 24 5A C7 07 B4 27
00A0 | E1 DA 7C 7E AA DB E1 DD 86 8B 81 B6 75 D5 16 E8
00B0 | DD 20 19 3F D5 1C AC DE 5A 22 81 DC C5 7A 72 4C
00C0 | 77 87 25 11 F7 D1 56 AA A0 32 C7 E7 31 F9 71 F3
00D0 | F4 C9 BE 92 33 A3 A1 EE 78 2C 33 11 B0 D3 80 C0
00E0 | 63 93 86 B5 73 66 AB 38 CA 23 2B 08 80 50 95 D1
00F0 | 82 C1 38 2F 1E 02 74 D3 EA E5 9F 08 AB 7C 8F 50
0100 | BB 9C E7 5A B7 A2 B7 27 A0 52 F7 20 B1 15 BE 65
0110 | F4 55 12 8B 02 BF 18 2D 24 32 55 89 4E 1D 37 6C
0120 | 4B 28 7D 45 21 80 12 FB A1 B9 CD 76 19 B1 CF 82
0130 | 7F EA B4 E0 0E B9 72 2A 12 6C C0 22 A1 DD CC 09
0140 | 4F 3B 7F 25 8F DE E7 5F A2 1C 8D A6 1F 41 36 C2
0150 | 3B AD DB 0C
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 | F4DD0B006170466A |
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 | 51A1143FC7A3666BE4BE54D6890A02DC |
Value generated by client in Step 1 |
| server_nonce | 40, 16 | 63248F6748214EAB8A2F4CC876E11974 |
Value received from server in Step 2 |
| p | 56, 8 | 046A794259000000TL byte deserialization => bigendian conversion to decimal => 1786331737 |
First prime cofactor: single-byte prefix denoting length, 4-byte string, and three bytes of padding |
| q | 64, 8 | 047012C543000000TL byte deserialization => bigendian conversion to decimal => 1880278339 |
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 | FE00010007FB235B4C7728558405705E 3F18B09E5E2434977C42112E50DDE7C3 39D5893F966E40D8C951E37D9E325381 89A83D59E005502B7CC125FBCD346EE7 5E33D0A26EDFFF456914245AC707B427 E1DA7C7EAADBE1DD868B81B675D516E8 DD20193FD51CACDE5A2281DCC57A724C 77872511F7D156AAA032C7E731F971F3 F4C9BE9233A3A1EE782C3311B0D380C0 639386B57366AB38CA232B08805095D1 82C1382F1E0274D3EAE59F08AB7C8F50 BB9CE75AB7A2B727A052F720B115BE65 F455128B02BF182D243255894E1D376C 4B287D45218012FBA1B9CD7619B1CF82 7FEAB4E00EB9722A126CC022A1DDCC09 4F3B7F258FDEE75FA21C8DA61F4136C23BADDB0C |
Value generated above |
Received payload (excluding transport headers/trailers):
0000 | 00 00 00 00 00 00 00 00 01 C8 63 F4 61 70 46 6A
0010 | 78 02 00 00 5C 07 E8 D0 51 A1 14 3F C7 A3 66 6B
0020 | E4 BE 54 D6 89 0A 02 DC 63 24 8F 67 48 21 4E AB
0030 | 8A 2F 4C C8 76 E1 19 74 FE 50 02 00 C3 34 D3 13
0040 | 06 41 74 F4 43 CE 90 E1 3C 83 5F AE A6 AE 96 77
0050 | 08 9A 07 81 CC 8C 17 AD C8 FF 5B 50 72 93 4C 1D
0060 | FB 1F 2B 92 22 19 7D E8 06 18 6E 66 12 E0 CF A2
0070 | 59 38 09 B4 B9 1B 49 F0 06 FF BB D9 EA AA DE 1E
0080 | ED CA 04 6F 50 0A 77 BB 53 8E 3C 2F 02 A4 A6 81
0090 | 4D F0 BC 77 99 3E 49 3B 7F 2C 98 34 4F 67 44 55
00A0 | A9 0A 54 10 70 74 0F 4B 81 1F FF 4B 80 B1 61 73
00B0 | 7E 0E 86 7F F2 0D 03 BE 6B 52 BA 66 F7 31 9D 03
00C0 | B6 21 73 2E 1C 88 02 02 EA F6 1D F3 1D E8 31 E7
00D0 | AC 97 B0 FF DB FF FF A7 01 9D 39 95 53 F3 7B 64
00E0 | 59 13 23 84 43 F4 C5 60 A5 9A 5B A6 AA 6B FA EB
00F0 | 15 9F D2 29 1F CD A4 9A 23 E8 00 91 96 B8 06 2D
0100 | D4 24 F4 5D 3B 43 53 8C 68 B2 C0 70 A8 45 C2 60
0110 | 05 2D D3 C2 66 65 9F A6 C0 C6 A8 FF 36 FB FF 8D
0120 | AB 36 E0 6B EB 5E 18 AF E3 80 27 FD A4 5E 65 88
0130 | 4A 50 34 02 84 0E 21 C1 86 91 01 F4 C6 13 E9 ED
0140 | A6 1C 2E B0 AA 98 70 46 F8 06 9C 2C 00 2E E4 8A
0150 | 95 84 4D D6 2E 0E 4B 61 22 57 39 1B 01 4D 3B 04
0160 | 3D 7C 19 3F 93 63 52 F9 D7 99 CC 40 17 CA 54 48
0170 | 96 BB 09 B3 B5 B8 B7 0C 2C 5E 48 29 5A 82 CF 13
0180 | BC F5 FB 0B A5 29 91 EC 5C 25 18 8A B7 83 CB CE
0190 | D3 57 3B AB B2 55 E8 27 41 EA F4 94 16 09 AE FF
01A0 | 96 0A 4F 2B 41 F9 2E 78 59 51 41 EB C7 36 77 E0
01B0 | 91 04 B8 69 0D 3E 3C 30 FC A7 8B B0 F9 7B 43 36
01C0 | E9 25 BC B0 C8 5A 80 54 58 EE 7B 8D AD 75 99 38
01D0 | 8C 33 83 94 FB 31 7C 0C 6B D5 EC 2C D5 64 17 7E
01E0 | C0 59 E9 70 5E FA F2 04 8E D0 B0 14 EA 89 C6 0E
01F0 | E4 8C C5 47 FE 51 CE 4D 0F 13 DE A2 AB EA 9F 24
0200 | 25 B3 FA 29 87 D9 60 ED EF 61 9B 67 92 1B 2E 92
0210 | 21 9C 81 F7 09 C2 92 44 14 93 22 57 D5 F3 EE B1
0220 | 2D 0A AF 2B 29 51 19 88 DA CC 96 67 92 D7 E2 6F
0230 | 04 EF 5F 78 CC 18 F8 A9 C6 20 66 8F D7 6A 66 8A
0240 | C6 E6 D4 34 74 BF B5 CF C9 27 C1 5B 5D 1F D5 31
0250 | F5 0B 7E DF FC D5 0F 6F 04 A0 88 45 66 CC 85 8D
0260 | 05 A2 B8 46 D6 9A 87 99 D3 60 22 11 2A CC CA 56
0270 | 7D 6B 5E FE 79 9A C9 3D E4 39 A7 D1 6C E6 1C 16
0280 | B0 2F 89 AD 9A CB D0 45 11 1B C5 F1
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 | 01C863F46170466A |
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 | 51A1143FC7A3666BE4BE54D6890A02DC |
Value generated by client in Step 1 |
| server_nonce | 40, 16 | 63248F6748214EAB8A2F4CC876E11974 |
Value received from server in Step 2 |
| encrypted_answer | 56, 596 | FE500200C334D313064174F443CE90E1 3C835FAEA6AE9677089A0781CC8C17AD C8FF5B5072934C1DFB1F2B9222197DE8 06186E6612E0CFA2593809B4B91B49F0 06FFBBD9EAAADE1EEDCA046F500A77BB 538E3C2F02A4A6814DF0BC77993E493B 7F2C98344F674455A90A541070740F4B 811FFF4B80B161737E0E867FF20D03BE 6B52BA66F7319D03B621732E1C880202 EAF61DF31DE831E7AC97B0FFDBFFFFA7 019D399553F37B645913238443F4C560 A59A5BA6AA6BFAEB159FD2291FCDA49A 23E8009196B8062DD424F45D3B43538C 68B2C070A845C260052DD3C266659FA6 C0C6A8FF36FBFF8DAB36E06BEB5E18AF E38027FDA45E65884A503402840E21C1 869101F4C613E9EDA61C2EB0AA987046 F8069C2C002EE48A95844DD62E0E4B61 2257391B014D3B043D7C193F936352F9 D799CC4017CA544896BB09B3B5B8B70C 2C5E48295A82CF13BCF5FB0BA52991EC 5C25188AB783CBCED3573BABB255E827 41EAF4941609AEFF960A4F2B41F92E78 595141EBC73677E09104B8690D3E3C30 FCA78BB0F97B4336E925BCB0C85A8054 58EE7B8DAD7599388C338394FB317C0C 6BD5EC2CD564177EC059E9705EFAF204 8ED0B014EA89C60EE48CC547FE51CE4D 0F13DEA2ABEA9F2425B3FA2987D960ED EF619B67921B2E92219C81F709C29244 14932257D5F3EEB12D0AAF2B29511988 DACC966792D7E26F04EF5F78CC18F8A9 C620668FD76A668AC6E6D43474BFB5CF C927C15B5D1FD531F50B7EDFFCD50F6F 04A0884566CC858D05A2B846D69A8799 D36022112ACCCA567D6B5EFE799AC93D E439A7D16CE61C16B02F89AD9ACBD045111BC5F1 |
See below |
Decrypt encrypted_answer using the reverse of the process specified in step 6:
encrypted_answer = C334D313064174F443CE90E13C835FAEA6AE9677089A0781CC8C17ADC8FF5B5072934C1DFB1F2B9222197DE806186E6612E0CFA2593809B4B91B49F006FFBBD9EAAADE1EEDCA046F500A77BB538E3C2F02A4A6814DF0BC77993E493B7F2C98344F674455A90A541070740F4B811FFF4B80B161737E0E867FF20D03BE6B52BA66F7319D03B621732E1C880202EAF61DF31DE831E7AC97B0FFDBFFFFA7019D399553F37B645913238443F4C560A59A5BA6AA6BFAEB159FD2291FCDA49A23E8009196B8062DD424F45D3B43538C68B2C070A845C260052DD3C266659FA6C0C6A8FF36FBFF8DAB36E06BEB5E18AFE38027FDA45E65884A503402840E21C1869101F4C613E9EDA61C2EB0AA987046F8069C2C002EE48A95844DD62E0E4B612257391B014D3B043D7C193F936352F9D799CC4017CA544896BB09B3B5B8B70C2C5E48295A82CF13BCF5FB0BA52991EC5C25188AB783CBCED3573BABB255E82741EAF4941609AEFF960A4F2B41F92E78595141EBC73677E09104B8690D3E3C30FCA78BB0F97B4336E925BCB0C85A805458EE7B8DAD7599388C338394FB317C0C6BD5EC2CD564177EC059E9705EFAF2048ED0B014EA89C60EE48CC547FE51CE4D0F13DEA2ABEA9F2425B3FA2987D960EDEF619B67921B2E92219C81F709C2924414932257D5F3EEB12D0AAF2B29511988DACC966792D7E26F04EF5F78CC18F8A9C620668FD76A668AC6E6D43474BFB5CFC927C15B5D1FD531F50B7EDFFCD50F6F04A0884566CC858D05A2B846D69A8799D36022112ACCCA567D6B5EFE799AC93DE439A7D16CE61C16B02F89AD9ACBD045111BC5F1
tmp_aes_key = 16F548177058E8D39C41CBAD4D419446BEB12EB9B8F5AD28EA824B8015F17D81
tmp_aes_iv = C4D14166C1378E35C698460047DBB6075441BE9984611C28837357EBBF8CB5BD
Yielding:
answer_with_hash = 8BB20017894315B136AE5F4BAAD0F0BA20334342BA0D89B551A1143FC7A3666BE4BE54D6890A02DC63248F6748214EAB8A2F4CC876E1197403000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001008539DB1E497692EE8BD112463F5F26699039792151BE8B575AA56D8914EDBAA242C2A8096FFAB06211B36291FC4994CB0FDFD37389DF8886F2C6B634C0D01B1C8EBD3E9BE1F49B4A8BD33C3952EF1CEC5E9425CD9C2136CA482A521F9ACC86BEA7D8E224F3D6D78A7F734961EED863EA52EC399C58AE94B733E4CB0AFC728926FB2F457D4AB89576D8067489E323DF8702DEC6EFA2EAF1D85548748D2DFA62925920563076F143D8AE852BCAE61553371BEDA580FEBD952AC7C7C1AFBB3F15934CE815716C6C362F9382BE91DC6F964E97C1A308D63FC1E4DFB2B8395A3E7B9A996C2DD3086488EB281301BEEC1ECEDD00296D76AC7EF7B786EA82F0FA7896DB6170466AA674223E982CE5E5
answer = BA0D89B551A1143FC7A3666BE4BE54D6890A02DC63248F6748214EAB8A2F4CC876E1197403000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE0001008539DB1E497692EE8BD112463F5F26699039792151BE8B575AA56D8914EDBAA242C2A8096FFAB06211B36291FC4994CB0FDFD37389DF8886F2C6B634C0D01B1C8EBD3E9BE1F49B4A8BD33C3952EF1CEC5E9425CD9C2136CA482A521F9ACC86BEA7D8E224F3D6D78A7F734961EED863EA52EC399C58AE94B733E4CB0AFC728926FB2F457D4AB89576D8067489E323DF8702DEC6EFA2EAF1D85548748D2DFA62925920563076F143D8AE852BCAE61553371BEDA580FEBD952AC7C7C1AFBB3F15934CE815716C6C362F9382BE91DC6F964E97C1A308D63FC1E4DFB2B8395A3E7B9A996C2DD3086488EB281301BEEC1ECEDD00296D76AC7EF7B786EA82F0FA7896DB6170466AA674223E982CE5E5
Generated payload (excluding transport headers/trailers):
0000 | BA 0D 89 B5 51 A1 14 3F C7 A3 66 6B E4 BE 54 D6
0010 | 89 0A 02 DC 63 24 8F 67 48 21 4E AB 8A 2F 4C C8
0020 | 76 E1 19 74 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 | 85 39 DB 1E 49 76 92 EE 8B D1 12 46 3F 5F 26 69
0140 | 90 39 79 21 51 BE 8B 57 5A A5 6D 89 14 ED BA A2
0150 | 42 C2 A8 09 6F FA B0 62 11 B3 62 91 FC 49 94 CB
0160 | 0F DF D3 73 89 DF 88 86 F2 C6 B6 34 C0 D0 1B 1C
0170 | 8E BD 3E 9B E1 F4 9B 4A 8B D3 3C 39 52 EF 1C EC
0180 | 5E 94 25 CD 9C 21 36 CA 48 2A 52 1F 9A CC 86 BE
0190 | A7 D8 E2 24 F3 D6 D7 8A 7F 73 49 61 EE D8 63 EA
01A0 | 52 EC 39 9C 58 AE 94 B7 33 E4 CB 0A FC 72 89 26
01B0 | FB 2F 45 7D 4A B8 95 76 D8 06 74 89 E3 23 DF 87
01C0 | 02 DE C6 EF A2 EA F1 D8 55 48 74 8D 2D FA 62 92
01D0 | 59 20 56 30 76 F1 43 D8 AE 85 2B CA E6 15 53 37
01E0 | 1B ED A5 80 FE BD 95 2A C7 C7 C1 AF BB 3F 15 93
01F0 | 4C E8 15 71 6C 6C 36 2F 93 82 BE 91 DC 6F 96 4E
0200 | 97 C1 A3 08 D6 3F C1 E4 DF B2 B8 39 5A 3E 7B 9A
0210 | 99 6C 2D D3 08 64 88 EB 28 13 01 BE EC 1E CE DD
0220 | 00 29 6D 76 AC 7E F7 B7 86 EA 82 F0 FA 78 96 DB
0230 | 61 70 46 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 | 51A1143FC7A3666BE4BE54D6890A02DC |
Value generated by client in Step 1 |
| server_nonce | 20, 16 | 63248F6748214EAB8A2F4CC876E11974 |
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 4B2454BF6F4FADF034B10403119CD8E3B92FCC5B |
2048-bit prime, in big-endian byte order, to be checked as specified in the auth key docs |
| g_a | 300, 260 | FE0001008539DB1E497692EE8BD11246 3F5F26699039792151BE8B575AA56D89 14EDBAA242C2A8096FFAB06211B36291 FC4994CB0FDFD37389DF8886F2C6B634 C0D01B1C8EBD3E9BE1F49B4A8BD33C39 52EF1CEC5E9425CD9C2136CA482A521F 9ACC86BEA7D8E224F3D6D78A7F734961 EED863EA52EC399C58AE94B733E4CB0A FC728926FB2F457D4AB89576D8067489 E323DF8702DEC6EFA2EAF1D85548748D 2DFA62925920563076F143D8AE852BCA E61553371BEDA580FEBD952AC7C7C1AF BB3F15934CE815716C6C362F9382BE91 DC6F964E97C1A308D63FC1E4DFB2B839 5A3E7B9A996C2DD3086488EB281301BE EC1ECEDD00296D76AC7EF7B786EA82F0FA7896DB |
g_a diffie-hellman parameter |
| server_time | 560, 4 | 6170466A (1783001185 in decimal) |
Server time |
First, generate a secure random 2048-bit number b:
b = 96E8D3D298D05AA574B92495F566D0C71C2CA5E1A1FCB18CEFF2408CC57F9E5D5EBD18F3DAFB5FA3DA41F6A73ADB14CF36642882D403A39FD640B9A3B4DEAD433DB0FFA55262EBC89A44324E6F3BEDEA1EB9CA19E465E1135B73497B8567ED842DFCC8F02EB2A8E4C8F923826CDF98D717FBF6F6D55313779163D40E3B18289A7BBCD9CC2B2280B888DCC36117E342D352BE67944CC9C723D928339877E7CB47917A582AB8DAB59A9BFFBEC88A21ECCAF93BAEF9AFB4EE3FB69FFF55A1D7EFAE03328C585E39750506D7C795E5737AFC3FF6CA79C7C205269A8BCB3F03D74DF36CE727E8E3D52663F208AE31B786EC852F1BA4C36EFEE2F8528AD1945E2C7ECF
Then compute g_b = pow(g, b) mod dh_prime
g_b = 2EE7B6CC1343B2D39A1AAB034551C9912E5DEE8047C6C62FFBD42B5E1894CFCB79EFEF794135A9FAA3F32C88D5D6D19F75289A5362984AC02A53A4E49E78C07E78C35FF505BC707F7F64E9AAA4BFBD0DBB11E3CACE330048C629DB154463731A2833E11130328EDE8C1230B246D1D999A0336CAC5B32BE5780253DE10BAA6513A5A079F2B9D6A59DB7799E97915F556C89407617BE822C7F65532C8E37792442EDD83793940F5606BC1994B4964ED3458C9AD513977F217699D32368315C7BB07D99C9EE77DE069E62E4A4DFDB16F4F911AA1AEF7373A2F49185501BE684A777772BFC4BD99E38FA51014A3E059543BDCF213977FE913E8A3D881C2EB5523B04
Generated payload (excluding transport headers/trailers):
0000 | 54 B6 43 66 51 A1 14 3F C7 A3 66 6B E4 BE 54 D6
0010 | 89 0A 02 DC 63 24 8F 67 48 21 4E AB 8A 2F 4C C8
0020 | 76 E1 19 74 00 00 00 00 00 00 00 00 FE 00 01 00
0030 | 2E E7 B6 CC 13 43 B2 D3 9A 1A AB 03 45 51 C9 91
0040 | 2E 5D EE 80 47 C6 C6 2F FB D4 2B 5E 18 94 CF CB
0050 | 79 EF EF 79 41 35 A9 FA A3 F3 2C 88 D5 D6 D1 9F
0060 | 75 28 9A 53 62 98 4A C0 2A 53 A4 E4 9E 78 C0 7E
0070 | 78 C3 5F F5 05 BC 70 7F 7F 64 E9 AA A4 BF BD 0D
0080 | BB 11 E3 CA CE 33 00 48 C6 29 DB 15 44 63 73 1A
0090 | 28 33 E1 11 30 32 8E DE 8C 12 30 B2 46 D1 D9 99
00A0 | A0 33 6C AC 5B 32 BE 57 80 25 3D E1 0B AA 65 13
00B0 | A5 A0 79 F2 B9 D6 A5 9D B7 79 9E 97 91 5F 55 6C
00C0 | 89 40 76 17 BE 82 2C 7F 65 53 2C 8E 37 79 24 42
00D0 | ED D8 37 93 94 0F 56 06 BC 19 94 B4 96 4E D3 45
00E0 | 8C 9A D5 13 97 7F 21 76 99 D3 23 68 31 5C 7B B0
00F0 | 7D 99 C9 EE 77 DE 06 9E 62 E4 A4 DF DB 16 F4 F9
0100 | 11 AA 1A EF 73 73 A2 F4 91 85 50 1B E6 84 A7 77
0110 | 77 2B FC 4B D9 9E 38 FA 51 01 4A 3E 05 95 43 BD
0120 | CF 21 39 77 FE 91 3E 8A 3D 88 1C 2E B5 52 3B 04
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 | 51A1143FC7A3666BE4BE54D6890A02DC |
Value generated by client in Step 1 |
| server_nonce | 20, 16 | 63248F6748214EAB8A2F4CC876E11974 |
Value received from server in Step 2 |
| g_b | 36, 260 | FE0001002EE7B6CC1343B2D39A1AAB03 4551C9912E5DEE8047C6C62FFBD42B5E 1894CFCB79EFEF794135A9FAA3F32C88 D5D6D19F75289A5362984AC02A53A4E4 9E78C07E78C35FF505BC707F7F64E9AA A4BFBD0DBB11E3CACE330048C629DB15 4463731A2833E11130328EDE8C1230B2 46D1D999A0336CAC5B32BE5780253DE1 0BAA6513A5A079F2B9D6A59DB7799E97 915F556C89407617BE822C7F65532C8E 37792442EDD83793940F5606BC1994B4 964ED3458C9AD513977F217699D32368 315C7BB07D99C9EE77DE069E62E4A4DF DB16F4F911AA1AEF7373A2F49185501B E684A777772BFC4BD99E38FA51014A3E 059543BDCF213977FE913E8A3D881C2EB5523B04 |
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 = 54B6436651A1143FC7A3666BE4BE54D6890A02DC63248F6748214EAB8A2F4CC876E119740000000000000000FE0001002EE7B6CC1343B2D39A1AAB034551C9912E5DEE8047C6C62FFBD42B5E1894CFCB79EFEF794135A9FAA3F32C88D5D6D19F75289A5362984AC02A53A4E49E78C07E78C35FF505BC707F7F64E9AAA4BFBD0DBB11E3CACE330048C629DB154463731A2833E11130328EDE8C1230B246D1D999A0336CAC5B32BE5780253DE10BAA6513A5A079F2B9D6A59DB7799E97915F556C89407617BE822C7F65532C8E37792442EDD83793940F5606BC1994B4964ED3458C9AD513977F217699D32368315C7BB07D99C9EE77DE069E62E4A4DFDB16F4F911AA1AEF7373A2F49185501BE684A777772BFC4BD99E38FA51014A3E059543BDCF213977FE913E8A3D881C2EB5523B04
padding = A813B31F76CD0D537283454A
tmp_aes_key = 16F548177058E8D39C41CBAD4D419446BEB12EB9B8F5AD28EA824B8015F17D81
tmp_aes_iv = C4D14166C1378E35C698460047DBB6075441BE9984611C28837357EBBF8CB5BD
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 = 136CA7E1F58C243372404792D3519F815AA6EC5E0324B2B11D89197CE5FFCDC2E53C5444A399E9C2111C143D1DFDA34932FC5F290EF51E28BE6AD31F68FB6CE9A8273EAD64262D78A5E132E5789E2620CD9C6E4C0A259E8B154FB07BA4725E9F883D2FA8EC59CAA7F683586CC35C3231B2023675C2759CB4194F6BBBC46EA47827CF2B07242357B6FC300EF086AF41D98E06C4DE2FCC41CD9216AF01D30A0DBA421D928D1D7386ECA1D18CA6772466169173425C272A22D78D9E55BEA4DB25EB9BD32D31115563AE2BFCD0374CEAEF3E42661F9059228BFCA3DF79F2E77C4AA5CBCF03963783CE0D6257399F7A4DD644BF1E57F19A9DF46172ECED9610C4F6A5A57FA4D08173732B1BA95B992B8B633A474A9D8FD18BDC673077178C5C20506FD226399C1F87D022C5C395428D92B8E4E39218EA68D3D6E010BBFFE839F8D124C5C458BCDF8FE5F25190F97C0C46C206
The length of the final string is 336 bytes.
Sent payload (excluding transport headers/trailers):
0000 | 00 00 00 00 00 00 00 00 E0 73 0E 00 61 70 46 6A
0010 | 78 01 00 00 1F 5F 04 F5 51 A1 14 3F C7 A3 66 6B
0020 | E4 BE 54 D6 89 0A 02 DC 63 24 8F 67 48 21 4E AB
0030 | 8A 2F 4C C8 76 E1 19 74 FE 50 01 00 13 6C A7 E1
0040 | F5 8C 24 33 72 40 47 92 D3 51 9F 81 5A A6 EC 5E
0050 | 03 24 B2 B1 1D 89 19 7C E5 FF CD C2 E5 3C 54 44
0060 | A3 99 E9 C2 11 1C 14 3D 1D FD A3 49 32 FC 5F 29
0070 | 0E F5 1E 28 BE 6A D3 1F 68 FB 6C E9 A8 27 3E AD
0080 | 64 26 2D 78 A5 E1 32 E5 78 9E 26 20 CD 9C 6E 4C
0090 | 0A 25 9E 8B 15 4F B0 7B A4 72 5E 9F 88 3D 2F A8
00A0 | EC 59 CA A7 F6 83 58 6C C3 5C 32 31 B2 02 36 75
00B0 | C2 75 9C B4 19 4F 6B BB C4 6E A4 78 27 CF 2B 07
00C0 | 24 23 57 B6 FC 30 0E F0 86 AF 41 D9 8E 06 C4 DE
00D0 | 2F CC 41 CD 92 16 AF 01 D3 0A 0D BA 42 1D 92 8D
00E0 | 1D 73 86 EC A1 D1 8C A6 77 24 66 16 91 73 42 5C
00F0 | 27 2A 22 D7 8D 9E 55 BE A4 DB 25 EB 9B D3 2D 31
0100 | 11 55 63 AE 2B FC D0 37 4C EA EF 3E 42 66 1F 90
0110 | 59 22 8B FC A3 DF 79 F2 E7 7C 4A A5 CB CF 03 96
0120 | 37 83 CE 0D 62 57 39 9F 7A 4D D6 44 BF 1E 57 F1
0130 | 9A 9D F4 61 72 EC ED 96 10 C4 F6 A5 A5 7F A4 D0
0140 | 81 73 73 2B 1B A9 5B 99 2B 8B 63 3A 47 4A 9D 8F
0150 | D1 8B DC 67 30 77 17 8C 5C 20 50 6F D2 26 39 9C
0160 | 1F 87 D0 22 C5 C3 95 42 8D 92 B8 E4 E3 92 18 EA
0170 | 68 D3 D6 E0 10 BB FF E8 39 F8 D1 24 C5 C4 58 BC
0180 | DF 8F E5 F2 51 90 F9 7C 0C 46 C2 06
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 | E0730E006170466A |
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 | 51A1143FC7A3666BE4BE54D6890A02DC |
Value generated by client in Step 1 |
| server_nonce | 40, 16 | 63248F6748214EAB8A2F4CC876E11974 |
Value received from server in Step 2 |
| encrypted_data | 56, 340 | FE500100136CA7E1F58C243372404792 D3519F815AA6EC5E0324B2B11D89197C E5FFCDC2E53C5444A399E9C2111C143D 1DFDA34932FC5F290EF51E28BE6AD31F 68FB6CE9A8273EAD64262D78A5E132E5 789E2620CD9C6E4C0A259E8B154FB07B A4725E9F883D2FA8EC59CAA7F683586C C35C3231B2023675C2759CB4194F6BBB C46EA47827CF2B07242357B6FC300EF0 86AF41D98E06C4DE2FCC41CD9216AF01 D30A0DBA421D928D1D7386ECA1D18CA6 772466169173425C272A22D78D9E55BE A4DB25EB9BD32D31115563AE2BFCD037 4CEAEF3E42661F9059228BFCA3DF79F2 E77C4AA5CBCF03963783CE0D6257399F 7A4DD644BF1E57F19A9DF46172ECED96 10C4F6A5A57FA4D08173732B1BA95B99 2B8B633A474A9D8FD18BDC673077178C 5C20506FD226399C1F87D022C5C39542 8D92B8E4E39218EA68D3D6E010BBFFE8 39F8D124C5C458BCDF8FE5F25190F97C0C46C206 |
Encrypted client_DH_inner_data generated previously, serialized as a TL byte string |
The client computes the auth_key using formula g_a^b mod dh_prime:
auth_key = 8E1081A1B5CA1B399A9A9D7E08BB9A9182AB634F8C03F2A49F944E2F944A9C71EDBA61A32A70D3DADEB33752AE515B16B2D8E75039C40EBE18136775C3727372A8DF486606D671FD63842DF0A44ACC31E68B7B1EC6A731A1DC5C748F0CB46AC00FDE363F0520B51D9B59EAE519EA511A8E8591FC7010DF0B07CDBAB04013DD85172CB54555DC5C982EA0A5DCF4411E798D338B823161FD8C93100B7A426186B4C16F9113521081C8D2075872F4A0CF238034843DC01F2C26828721A2E2FFD93A9B0142B8DF6355C43D9AEF5B448F1CC0D84E0E72A7FF494D4CC3B1650050DDEC5DC321ADA68E420F45098280CEAB58A1CBFAA60FFF3218E56B4741143AC5A6F0
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 A4 4A EF 62 70 46 6A
0010 | 34 00 00 00 34 F7 CB 3B 51 A1 14 3F C7 A3 66 6B
0020 | E4 BE 54 D6 89 0A 02 DC 63 24 8F 67 48 21 4E AB
0030 | 8A 2F 4C C8 76 E1 19 74 AA 40 4B 58 DF 40 4D 8F
0040 | 36 37 72 B1 4C E5 A5 6F
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 | 01A44AEF6270466A |
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 | 51A1143FC7A3666BE4BE54D6890A02DC |
Value generated by client in Step 1 |
| server_nonce | 40, 16 | 63248F6748214EAB8A2F4CC876E11974 |
Value received from server in Step 2 |
| new_nonce_hash1 | 56, 16 | AA404B58DF404D8F363772B14CE5A56F |
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. |