diff --git a/data/web/corefork.telegram.org/mtproto/auth_key.html b/data/web/corefork.telegram.org/mtproto/auth_key.html index 518fc67cca..cc9bec5131 100644 --- a/data/web/corefork.telegram.org/mtproto/auth_key.html +++ b/data/web/corefork.telegram.org/mtproto/auth_key.html @@ -45,27 +45,19 @@

The query format is described using Binary Data Serialization and the TL Language. All large numbers are transmitted as strings containing the required sequence of bytes in big endian order. Hash functions, such as SHA1, return strings (of 20 bytes) which can also be interpreted as big endian numbers. Small numbers (int, long, int128, int256) are normally little endian; however, if they are part of SHA1, the bytes are not rearranged. This way, if long x is the 64 lower-order bits of SHA1 of string s, then the final 8 bytes of 20-byte string SHA1(s) are taken and interpreted as a 64-bit integer.

Prior to sending off unencrypted messages (required in this instance to generate an authorization key), the client must undergo (p,q) authorization as follows.

DH exchange initiation

-
    -
  1. Client sends query to server
  2. -
+
1) Client sends query to server
req_pq_multi#be7e8ef1 nonce:int128 = ResPQ;

The value of nonce is selected randomly by the client (random number) and identifies the client within this communication. Following this step, it is known to all.

-
    -
  1. Server sends response of the form
  2. -
+
2) Server sends response of the form
resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector long = ResPQ;

Here, string pq is a representation of a natural number (in binary big endian format). This number is the product of two different odd prime numbers. Normally, pq is less than or equal to 2^63-1. The value of server_nonce is selected randomly by the server; following this step, it is known to all.

server_public_key_fingerprints is a list of public RSA key fingerprints (64 lower-order bits of SHA1 (server_public_key); the public key is represented as a bare type rsa_public_key n:string e:string = RSAPublicKey, where, as usual, n and e are numbers in big endian format serialized as strings of bytes, following which SHA1 is computed) received by the server.

-

All subsequent messages contain the pair (nonce, server_nonce) both in the plain-text, and the encrypted portions which makes it possible to identify a “temporary session” — one run of the key generation protocol described on this page that uses the same (nonce, server_nonce) pair. An intruder could not create a parallel session with the server with the same parameters and reuse parts of server- or client-encrypted messages for its own purposes in such a parallel session, because a different server_nonce would be selected by the server for any new “temporary session”.

+

All subsequent messages contain the pair (nonce, server_nonce) both in the plain-text, and the encrypted portions which makes it possible to identify a “temporary session” — one run of the key generation protocol described on this page that uses the same (nonce, server_nonce) pair. An intruder could not create a parallel session with the server with the same parameters and reuse parts of server- or client-encrypted messages for its own purposes in such a parallel session, because a different server_nonce would be selected by the server for any new “temporary session”.

Proof of work

-
    -
  1. Client decomposes pq into prime factors such that p < q.
  2. -
+
3) Client decomposes pq into prime factors such that p < q.

This starts a round of Diffie-Hellman key exchanges.

Presenting proof of work; Server authentication

-
    -
  1. Client sends query to server
  2. -
+
4) Client sends query to server
req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params

Here, encrypted_data is obtained as follows:

Someone might intercept the query and replace it with their own, independently decomposing pq into factors instead of the client. The only field that it makes sense to modify is new_nonce which would be the one an intruder would have to re-generate (because an intruder cannot decrypt the encrypted data sent by the client). Since all subsequent messages are encrypted using new_nonce or contain new_nonce_hash, they will not be processed by the client (an intruder would not be able to make it look as though they had been generated by the server because they would not contain new_nonce). Therefore, this intercept will only result in the intruder's completing the authorization key generation protocol in place of the client and creating a new key (that has nothing to do with the client); however, the same effect could be achieved simply by creating a new key in one's own name.

-

An alternative form of inner data (p_q_inner_data_temp_dc) is used to create temporary keys, that are only stored in the server RAM and are discarded after at most expires_in seconds. The server is free to discard its copy earlier. In all other respects the temporary key generation protocol is the same. After a temporary key is created, the client usually binds it to its principal authorisation key by means of the auth.bindTempAuthKey method, and uses it for all client-server communication until it expires; then a new temporary key is generated. Thus Perfect Forward Secrecy (PFS) in client-server communication is achieved. Read more about PFS »

-

4.1) RSA_PAD(data, server_public_key) mentioned above is implemented as follows:

+

An alternative form of inner data (p_q_inner_data_temp_dc) is used to create temporary keys, that are only stored in the server RAM and are discarded after at most expires_in seconds. The server is free to discard its copy earlier. In all other respects the temporary key generation protocol is the same. After a temporary key is created, the client usually binds it to its principal authorisation key by means of the auth.bindTempAuthKey method, and uses it for all client-server communication until it expires; then a new temporary key is generated. Thus Perfect Forward Secrecy (PFS) in client-server communication is achieved. Read more about PFS »

+
4.1) RSA_PAD(data, server_public_key) mentioned above is implemented as follows:
-
    -
  1. Server responds with:
  2. -
+
5) Server responds with:
server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params;

If the query is incorrect, the server returns a -404 error and the handshake must be restarted (any subsequent request also returns -404, even if it is correct).
@@ -120,9 +110,7 @@ A -444 error may also be returned if a test DC ID is passed in If the verification takes too long time (which is the case for older mobile devices), one might initially run only 15 Miller--Rabin iterations for verifying primeness of p and (p - 1)/2 with error probability not exceeding one billionth, and do more iterations later in the background.

Another optimization is to embed into the client application code a small table with some known "good" couples (g,p) (or just known safe primes p, since the condition on g is easily verified during execution), checked during code generation phase, so as to avoid doing such verification during runtime altogether. Server changes these values rarely, thus one usually has to put the current value of server's dh_prime into such a table. For example, current value of dh_prime equals (in big-endian byte order)

C7 1C AE B9 C6 B1 C9 04 8E 6C 52 2F 70 F1 3F 73 98 0D 40 23 8E 3E 21 C1 49 34 D0 37 56 3D 93 0F 48 19 8A 0A A7 C1 40 58 22 94 93 D2 25 30 F4 DB FA 33 6F 6E 0A C9 25 13 95 43 AE D4 4C CE 7C 37 20 FD 51 F6 94 58 70 5A C6 8C D4 FE 6B 6B 13 AB DC 97 46 51 29 69 32 84 54 F1 8F AF 8C 59 5F 64 24 77 FE 96 BB 2A 94 1D 5B CD 1D 4A C8 CC 49 88 07 08 FA 9B 37 8E 3C 4F 3A 90 60 BE E6 7C F9 A4 A4 A6 95 81 10 51 90 7E 16 27 53 B5 6B 0F 6B 41 0D BA 74 D8 A8 4B 2A 14 B3 14 4E 0E F1 28 47 54 FD 17 ED 95 0D 59 65 B4 B9 DD 46 58 2D B1 17 8D 16 9C 6B C4 65 B0 D6 FF 9C A3 92 8F EF 5B 9A E4 E4 18 FC 15 E8 3E BE A0 F8 7F A9 FF 5E ED 70 05 0D ED 28 49 F4 7B F9 59 D9 56 85 0C E9 29 85 1F 0D 81 15 F6 35 B1 05 EE 2E 4E 15 D0 4B 24 54 BF 6F 4F AD F0 34 B1 04 03 11 9C D8 E3 B9 2F CC 5B
-
    -
  1. Client computes random 2048-bit number b (using a sufficient amount of entropy) and sends the server a message
  2. -
+
6) Client computes random 2048-bit number b (using a sufficient amount of entropy) and sends the server a message
set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:string = Set_client_DH_params_answer;

Here, encrypted_data is obtained thus:

The retry_id field is 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 9).

-
    -
  1. -

    Thereafter, auth_key equals pow(g, {ab}) mod dh_prime; on the server, it is computed as pow(g_b, a) mod dh_prime, and on the client as (g_a)^b mod dh_prime.

    -
  2. -
  3. -

    auth_key_hash is computed := 64 lower-order bits of SHA1 (auth_key). The server checks whether there already is another key with the same auth_key_hash and responds in one of the following ways.

    -
  4. -
+
7) Thereafter, auth_key equals pow(g, {ab}) mod dh_prime; on the server, it is computed as pow(g_b, a) mod dh_prime, and on the client as (g_a)^b mod dh_prime.
+
8) auth_key_hash is computed := 64 lower-order bits of SHA1 (auth_key). The server checks whether there already is another key with the same auth_key_hash and responds in one of the following ways.

DH key exchange complete

-
    -
  1. Server responds in one of three ways:
  2. -
+
9) Server responds in one of three ways:
dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;
 dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer;
 dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer;