mirror of
https://github.com/MarshalX/telegram-crawler.git
synced 2024-12-28 15:31:11 +01:00
Update content of files
This commit is contained in:
parent
32868361f6
commit
83f5a2b4c8
3 changed files with 88 additions and 90 deletions
|
@ -45,15 +45,11 @@
|
|||
<div id="dev_page_content"><!-- scroll_nav -->
|
||||
|
||||
<blockquote>
|
||||
<p>This article on MTProto's End-to-End encryption is meant for <strong>advanced users</strong>.
|
||||
If you want to learn more about <a href="https://telegram.org/faq#secret-chats">Secret Chats</a> from a less intimidating source, kindly see our <a href="https://telegram.org/faq#secret-chats">general FAQ</a>.</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>Note that as of version 4.6, major Telegram clients are using <strong>MTProto 2.0</strong>.
|
||||
MTProto v.1.0 is deprecated and is currently being phased out.</p>
|
||||
<p>This article on MTProto's End-to-End encryption is meant for <strong>advanced users</strong>.<br>If you want to learn more about <a href="https://telegram.org/faq#secret-chats">Secret Chats</a> from a less intimidating source, kindly see our <a href="https://telegram.org/faq#secret-chats">general FAQ</a>.</p>
|
||||
<p>Note that as of version 4.6, major Telegram clients are using <strong>MTProto 2.0</strong>.<br>MTProto v.1.0 is deprecated and is currently being phased out.</p>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<h5><a class="anchor" href="#related-articles" id="related-articles" name="related-articles"><i class="anchor-icon"></i></a>Related articles</h5>
|
||||
<h5><a class="anchor" name="related-articles" href="#related-articles"><i class="anchor-icon"></i></a>Related articles</h5>
|
||||
<p><div class="dev_page_nav_wrap"></p>
|
||||
<ul>
|
||||
<li><a href="/mtproto/security_guidelines">Security guidelines for developers</a></li>
|
||||
|
@ -63,13 +59,13 @@ MTProto v.1.0 is deprecated and is currently being phased out.</p>
|
|||
</ul>
|
||||
<p></div></p>
|
||||
<hr>
|
||||
<p>Secret Chats are one-on-one chats wherein messages are encrypted with a key held only by the chat's participants. Note that the <a href="/schema/end-to-end">schema</a> for these end-to-end encrypted Secret Chats is different from what is used for <a href="/mtproto">cloud chats</a>:</p>
|
||||
<p>Secret Chats are one-on-one chats wherein messages are encrypted with a key held only by the chat's participants. Note that the <a href="/schema/end-to-end">schema</a> for these end-to-end encrypted Secret Chats is different from what is used for <a href="/mtproto">cloud chats</a>:</p>
|
||||
<div>
|
||||
<a href="/file/811140633/4/hHw6Zy2DPyQ.109500/cabc10049a7190694f" target="_blank"><img src="/file/811140633/4/hHw6Zy2DPyQ.109500/cabc10049a7190694f" title="End-to-end encryption in MTProto 2.0 (Secret Chats)" class="dev_page_image" style="max-width: 600px"></a>
|
||||
<a href="/file/811140633/4/hHw6Zy2DPyQ.109500/cabc10049a7190694f" target="_blank"><img src="/file/811140633/4/hHw6Zy2DPyQ.109500/cabc10049a7190694f" title="End-to-end encryption in MTProto 2.0 (Secret Chats)" class="dev_page_image" style="max-width: 600px" /></a>
|
||||
</div>
|
||||
<h4><a class="anchor" href="#a-note-on-mtproto-20" id="a-note-on-mtproto-20" name="a-note-on-mtproto-20"><i class="anchor-icon"></i></a>A note on MTProto 2.0</h4>
|
||||
<p>This article describes the end-to-end encryption layer in the MTProto protocol version <strong>2.0</strong>.
|
||||
The principal differences from version 1.0 (<a href="/api/end-to-end_v1">described here</a> for reference) are as follows:</p>
|
||||
|
||||
<h4><a class="anchor" name="a-note-on-mtproto-2-0" href="#a-note-on-mtproto-2-0"><i class="anchor-icon"></i></a>A note on MTProto 2.0</h4>
|
||||
<p>This article describes the end-to-end encryption layer in the MTProto protocol version <strong>2.0</strong>.<br>The principal differences from version 1.0 (<a href="/api/end-to-end_v1">described here</a> for reference) are as follows:</p>
|
||||
<ul>
|
||||
<li>SHA-256 is used instead of SHA-1;</li>
|
||||
<li>Padding bytes are involved in the computation of msg_key;</li>
|
||||
|
@ -77,35 +73,34 @@ The principal differences from version 1.0 (<a href="/api/end-to-end_v1">describ
|
|||
<li>12..1024 padding bytes are used instead of 0..15 padding bytes in v.1.0.</li>
|
||||
</ul>
|
||||
<p>See also: <a href="https://core.telegram.org/mtproto">MTProto 2.0: Cloud Chats, server-client encryption</a></p>
|
||||
<h3><a class="anchor" href="#key-generation" id="key-generation" name="key-generation"><i class="anchor-icon"></i></a>Key Generation</h3>
|
||||
<h3><a class="anchor" name="key-generation" href="#key-generation"><i class="anchor-icon"></i></a>Key Generation</h3>
|
||||
<p>Keys are generated using the <a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange">Diffie-Hellman protocol</a>.</p>
|
||||
<p>Let us consider the following scenario: User <strong>A</strong> would like to initiate end-to-end encrypted communication with User <strong>B</strong>.</p>
|
||||
<h4><a class="anchor" href="#sending-a-request" id="sending-a-request" name="sending-a-request"><i class="anchor-icon"></i></a>Sending a Request</h4>
|
||||
<h4><a class="anchor" name="sending-a-request" href="#sending-a-request"><i class="anchor-icon"></i></a>Sending a Request</h4>
|
||||
<p>User <strong>A</strong> executes <a href="/method/messages.getDhConfig">messages.getDhConfig</a> to obtain the Diffie-Hellman parameters: a prime <strong>p</strong>, and a high-order element <strong>g</strong>.</p>
|
||||
<p>Executing this method before each new key generation procedure is of vital importance. It makes sense to cache the values of the parameters together with the version in order to avoid having to receive all of the values every time. If the version stored on the client is still up-to-date, the server will return the constructor <a href="/constructor/messages.dhConfigNotModified">messages.dhConfigNotModified</a>.</p>
|
||||
<p>The client is expected to check whether <strong>p</strong> is a safe 2048-bit prime (meaning that both <strong>p</strong> and <strong>(p-1)/2</strong> are prime, and that 2^2047 < p < 2^2048), and that <strong>g</strong> generates a cyclic subgroup of prime order <strong>(p-1)/2</strong>, i.e. is a quadratic residue <strong>mod p</strong>. Since <strong>g</strong> is always equal to 2, 3, 4, 5, 6 or 7, this is easily done using quadratic reciprocity law, yielding a simple condition on <strong>p mod 4g</strong> -- namely, <strong>p mod 8 = 7</strong> for <strong>g = 2</strong>; <strong>p mod 3 = 2</strong> for <strong>g = 3</strong>; no extra condition for <strong>g = 4</strong>; <strong>p mod 5 = 1 or 4</strong> for <strong>g = 5</strong>; <strong>p mod 24 = 19 or 23</strong> for <strong>g = 6</strong>; and <strong>p mod 7 = 3, 5 or 6</strong> for <strong>g = 7</strong>. After <strong>g</strong> and <strong>p</strong> have been checked by the client, it makes sense to cache the result, so as to avoid repeating lengthy computations in the future. This cache might be shared with one used for <a href="/mtproto/auth_key">Authorization Key generation</a>.</p>
|
||||
<p>If the client needs additional entropy for the random number generator, it can pass the <strong>random_length</strong> parameter (random_length> 0) so the server generates its own random sequence <strong>random</strong> of the appropriate length.
|
||||
<strong>Important</strong>: using the server's random sequence in its raw form may be unsafe, it must be combined with a client sequence.</p>
|
||||
<p>Client <strong>A</strong> computes a 2048-bit number <strong>a</strong> (using sufficient entropy or the server's <strong>random</strong>; see above) and executes <a href="/method/messages.requestEncryption">messages.requestEncryption</a> after passing in <code>g_a := pow(g, a) mod dh_prime</code>.</p>
|
||||
<p>The client is expected to check whether <strong>p</strong> is a safe 2048-bit prime (meaning that both <strong>p</strong> and <strong>(p-1)/2</strong> are prime, and that 2<sup>2047 < p < 2</sup>2048), and that <strong>g</strong> generates a cyclic subgroup of prime order <strong>(p-1)/2</strong>, i.e. is a quadratic residue <strong>mod p</strong>. Since <strong>g</strong> is always equal to 2, 3, 4, 5, 6 or 7, this is easily done using quadratic reciprocity law, yielding a simple condition on <strong>p mod 4g</strong> — namely, <strong>p mod 8 = 7</strong> for <strong>g = 2</strong>; <strong>p mod 3 = 2</strong> for <strong>g = 3</strong>; no extra condition for <strong>g = 4</strong>; <strong>p mod 5 = 1 or 4</strong> for <strong>g = 5</strong>; <strong>p mod 24 = 19 or 23</strong> for <strong>g = 6</strong>; and <strong>p mod 7 = 3, 5 or 6</strong> for <strong>g = 7</strong>. After <strong>g</strong> and <strong>p</strong> have been checked by the client, it makes sense to cache the result, so as to avoid repeating lengthy computations in the future. This cache might be shared with one used for <a href="/mtproto/auth_key">Authorization Key generation</a>.</p>
|
||||
<p>If the client needs additional entropy for the random number generator, it can pass the <strong>random_length</strong> parameter (random_length> 0) so the server generates its own random sequence <strong>random</strong> of the appropriate length.<br><strong>Important</strong>: using the server's random sequence in its raw form may be unsafe, it must be combined with a client sequence.</p>
|
||||
<p>Client <strong>A</strong> computes a 2048-bit number <strong>a</strong> (using sufficient entropy or the server's <strong>random</strong>; see above) and executes <a href="/method/messages.requestEncryption">messages.requestEncryption</a> after passing in <code>g_a := pow(g, a) mod dh_prime</code>.</p>
|
||||
<p>User <strong>B</strong> receives the update <a href="/constructor/updateEncryption">updateEncryption</a> for all associated authorization keys (all authorized devices) with the chat constructor <a href="/constructor/encryptedChatRequested">encryptedChatRequested</a>. The user must be shown basic information about User <strong>A</strong> and must be prompted to accept or reject the request.</p>
|
||||
<p>Both clients are to check that <strong>g</strong>, <strong>g_a</strong> and <strong>g_b</strong> are greater than one and smaller than <strong>p-1</strong>. We recommend checking that <strong>g_a</strong> and <strong>g_b</strong> are between <strong>2^{2048-64}</strong> and <strong>p - 2^{2048-64}</strong> as well.</p>
|
||||
<h4><a class="anchor" href="#accepting-a-request" id="accepting-a-request" name="accepting-a-request"><i class="anchor-icon"></i></a>Accepting a Request</h4>
|
||||
<h4><a class="anchor" name="accepting-a-request" href="#accepting-a-request"><i class="anchor-icon"></i></a>Accepting a Request</h4>
|
||||
<p>After User <strong>B</strong> confirms the creation of a secret chat with <strong>A</strong> in the client interface, Client <strong>B</strong> also receives up-to-date configuration parameters for the Diffie-Hellman method. Thereafter, it generates a random 2048-bit number, <strong>b</strong>, using rules similar to those for <strong>a</strong>. </p>
|
||||
<p>Having received <strong>g_a</strong> from the update with <a href="/constructor/encryptedChatRequested">encryptedChatRequested</a>, it can immediately generate the final shared key: <code>key = (pow(g_a, b) mod dh_prime)</code>. If key length < 256 bytes, add several leading zero bytes as padding — so that the key is exactly 256 bytes long. Its fingerprint, <strong>key_fingerprint</strong>, is equal to the 64 last bits of SHA1 (key). </p>
|
||||
<p><strong>Note 1:</strong> in this particular case SHA1 is used here even for MTProto 2.0 secret chats. </p>
|
||||
<p><strong>Note 2:</strong> this fingerprint is used as a sanity check for the key exchange procedure to detect bugs when developing client software — it is not connected to the key visualization used on the clients as means of external authentication in secret chats. <a href="/api/end-to-end/pfs#key-visualization">Key visualizations</a> on the clients are generated using the first 128 bits of SHA1(initial key) followed by the first 160 bits of SHA256(key used when secret chat was updated to layer 46).</p>
|
||||
<p>Client <strong>B</strong> executes <a href="/method/messages.acceptEncryption">messages.acceptEncryption</a> after passing it <code>g_b := pow(g, b) mod dh_prime</code> and <strong>key_fingerprint</strong>.</p>
|
||||
<p>For all of Client <strong>B's</strong> authorized devices, except the current one, <a href="/constructor/updateEncryption">updateEncryption</a> updates are sent with the constructor <a href="/constructor/encryptedChatDiscarded">encryptedChatDiscarded</a>. Thereafter, the only device that will be able to access the secret chat is Device <strong>B</strong>, which made the call to <a href="/method/messages.acceptEncryption">messages.acceptEncryption</a>.</p>
|
||||
<p>For all of Client <strong>B's</strong> authorized devices, except the current one, <a href="/constructor/updateEncryption">updateEncryption</a> updates are sent with the constructor <a href="/constructor/encryptedChatDiscarded">encryptedChatDiscarded</a>. Thereafter, the only device that will be able to access the secret chat is Device <strong>B</strong>, which made the call to <a href="/method/messages.acceptEncryption">messages.acceptEncryption</a>.</p>
|
||||
<p>User <strong>A</strong> will be sent an <a href="/constructor/updateEncryption">updateEncryption</a> update with the constructor <a href="/constructor/encryptedChat">encryptedChat</a>, for the authorization key that initiated the chat.</p>
|
||||
<p>With <strong>g_b</strong> from the update, Client <strong>A</strong> can also compute the shared key <code>key = (pow(g_b, a) mod dh_prime)</code>. If key length < 256 bytes, add several leading zero bytes as padding — so that the key is exactly 256 bytes long. If the fingerprint for the received key is identical to the one that was passed to <a href="/constructor/encryptedChat">encryptedChat</a>, incoming messages can be sent and processed. Otherwise, <a href="/method/messages.discardEncryption">messages.discardEncryption</a> must be executed and the user notified.</p>
|
||||
<h4><a class="anchor" href="#perfect-forward-secrecy" id="perfect-forward-secrecy" name="perfect-forward-secrecy"><i class="anchor-icon"></i></a>Perfect Forward Secrecy</h4>
|
||||
<h4><a class="anchor" name="perfect-forward-secrecy" href="#perfect-forward-secrecy"><i class="anchor-icon"></i></a>Perfect Forward Secrecy</h4>
|
||||
<p>In order to keep past communications safe, official Telegram clients will initiate re-keying once a key has been used to decrypt and encrypt more than 100 messages, or has been in use for more than one week, provided the key has been used to encrypt at least one message. Old keys are then securely discarded and cannot be reconstructed, even with access to the new keys currently in use.</p>
|
||||
<blockquote>
|
||||
<p>The re-keying protocol is further described in this article: <a href="/api/end-to-end/pfs">Perfect Forward Secrecy in Secret Chats</a>.</p>
|
||||
</blockquote>
|
||||
<p>Please note that your client must support Forward Secrecy in Secret Chats to be compatible with official Telegram clients. </p>
|
||||
<h3><a class="anchor" href="#sending-and-receiving-messages-in-a-secret-chat" id="sending-and-receiving-messages-in-a-secret-chat" name="sending-and-receiving-messages-in-a-secret-chat"><i class="anchor-icon"></i></a>Sending and Receiving Messages in a Secret Chat</h3>
|
||||
<h4><a class="anchor" href="#serialization-and-encryption-of-outgoing-messages" id="serialization-and-encryption-of-outgoing-messages" name="serialization-and-encryption-of-outgoing-messages"><i class="anchor-icon"></i></a>Serialization and Encryption of Outgoing Messages</h4>
|
||||
<h3><a class="anchor" name="sending-and-receiving-messages-in-a-secret-chat" href="#sending-and-receiving-messages-in-a-secret-chat"><i class="anchor-icon"></i></a>Sending and Receiving Messages in a Secret Chat</h3>
|
||||
<h4><a class="anchor" name="serialization-and-encryption-of-outgoing-messages" href="#serialization-and-encryption-of-outgoing-messages"><i class="anchor-icon"></i></a>Serialization and Encryption of Outgoing Messages</h4>
|
||||
<p>A TL object of type <a href="/type/DecryptedMessage">DecryptedMessage</a> is created and contains the message in plain text. For backward compatibility, the object must be wrapped in the constructor <a href="/constructor/decryptedMessageLayer">decryptedMessageLayer</a> with an indication of the supported layer (starting with 46).</p>
|
||||
<blockquote>
|
||||
<p>The TL-Schema for the contents of end-to-end encrypted messages is available <a href="/schema/end-to-end">here »</a></p>
|
||||
|
@ -126,49 +121,47 @@ The principal differences from version 1.0 (<a href="/api/end-to-end_v1">describ
|
|||
<p><em>For the obsolete MTProto 1.0, msg_key, aes_key, and aes_iv were computed differently (see <a href="/api/end-to-end_v1#serialization-and-encryption-of-outgoing-messages">this document</a> for reference).</em></p>
|
||||
<p>Data is encrypted with a 256-bit key, <strong>aes_key</strong>, and a 256-bit initialization vector, <strong>aes-iv</strong>, using AES-256 encryption with infinite garble extension (IGE). Encryption key fingerprint <strong>key_fingerprint</strong> and the message key <strong>msg_key</strong> are added at the top of the resulting byte array.</p>
|
||||
<p>Encrypted data is embedded into a <a href="/method/messages.sendEncrypted">messages.sendEncrypted</a> API call and passed to Telegram server for delivery to the other party of the Secret Chat.</p>
|
||||
<h4><a class="anchor" href="#upgrading-to-mtproto-20-from-mtproto-10" id="upgrading-to-mtproto-20-from-mtproto-10" name="upgrading-to-mtproto-20-from-mtproto-10"><i class="anchor-icon"></i></a>Upgrading to MTProto 2.0 from MTProto 1.0</h4>
|
||||
<h4><a class="anchor" name="upgrading-to-mtproto-2-0-from-mtproto-1-0" href="#upgrading-to-mtproto-2-0-from-mtproto-1-0"><i class="anchor-icon"></i></a>Upgrading to MTProto 2.0 from MTProto 1.0</h4>
|
||||
<p>As soon as both parties in a secret chat are using at least Layer 73, they should only use MTProto 2.0 for all outgoing messages. Some of the first received messages may use MTProto 1.0, if a sufficiently high starting layer has not been negotiated during the creation of the secret chat. After the first message encrypted with MTProto 2.0 (or the first message with Layer 73 or higher) is received, all messages with higher <a href="#sequence-numbers">sequence numbers</a> must be encrypted with MTProto 2.0 as well.</p>
|
||||
<p>As long as the current layer is lower than 73, each party should try to decrypt received messages with MTProto 1.0, and if this is not successful (msg_key does not match), try MTProto 2.0. Once the first MTProto 2.0-encrypted message arrives (or the layer is upgraded to 73), there is no need to try MTProto 1.0 decryption for any of the further messages (unless the client is still waiting for some gaps to be closed).</p>
|
||||
<h4><a class="anchor" href="#decrypting-an-incoming-message" id="decrypting-an-incoming-message" name="decrypting-an-incoming-message"><i class="anchor-icon"></i></a>Decrypting an Incoming Message</h4>
|
||||
<p>The steps above are performed in reverse order.
|
||||
When an encrypted message is received, you <strong>must</strong> check that msg_key is <strong>in fact</strong> equal to the 128 middle bits of the SHA256 hash of the decrypted message, prepended by 32 bytes taken from the shared <strong>key</strong>.
|
||||
If the message layer is greater than the one supported by the client, the user must be notified that the client version is out of date and prompted to update.</p>
|
||||
<h4><a class="anchor" href="#sequence-numbers" id="sequence-numbers" name="sequence-numbers"><i class="anchor-icon"></i></a>Sequence numbers</h4>
|
||||
<h4><a class="anchor" name="decrypting-an-incoming-message" href="#decrypting-an-incoming-message"><i class="anchor-icon"></i></a>Decrypting an Incoming Message</h4>
|
||||
<p>The steps above are performed in reverse order.<br>When an encrypted message is received, you <strong>must</strong> check that msg_key is <strong>in fact</strong> equal to the 128 middle bits of the SHA256 hash of the decrypted message, prepended by 32 bytes taken from the shared <strong>key</strong>.<br>If the message layer is greater than the one supported by the client, the user must be notified that the client version is out of date and prompted to update.</p>
|
||||
<h4><a class="anchor" name="sequence-numbers" href="#sequence-numbers"><i class="anchor-icon"></i></a>Sequence numbers</h4>
|
||||
<p>It is necessary to interpret all messages in their original order to protect against possible manipulations. Secret chats support a special mechanism for handling seq_no counters independently from the server.</p>
|
||||
<blockquote>
|
||||
<p>Proper handling of these counters is further described in this article: <a href="/api/end-to-end/seq_no">Sequence numbers in Secret Chats</a>.</p>
|
||||
</blockquote>
|
||||
<p>Please note that your client must support sequence numbers in Secret Chats to be compatible with official Telegram clients. </p>
|
||||
<h4><a class="anchor" href="#sending-encrypted-files" id="sending-encrypted-files" name="sending-encrypted-files"><i class="anchor-icon"></i></a>Sending Encrypted Files</h4>
|
||||
<p>All files sent to secret chats are encrypted with one-time keys that are in no way related to the chat's shared key. Before an encrypted file is sent, it is assumed that the encrypted file's address will be attached to the outside of an encrypted message using the <strong>file</strong> parameter of the <a href="/method/messages.sendEncryptedFile">messages.sendEncryptedFile</a> method and that the key for direct decryption will be sent in the body of the message (the <strong>key</strong> parameter in the constructors <a href="/constructor/decryptedMessageMediaPhoto">decryptedMessageMediaPhoto</a>, <a href="/constructor/decryptedMessageMediaPhoto">decryptedMessageMediaVideo</a> and <a href="/constructor/decryptedMessageMediaPhoto">decryptedMessageMediaFile</a>.</p>
|
||||
<h4><a class="anchor" name="sending-encrypted-files" href="#sending-encrypted-files"><i class="anchor-icon"></i></a>Sending Encrypted Files</h4>
|
||||
<p>All files sent to secret chats are encrypted with one-time keys that are in no way related to the chat's shared key. Before an encrypted file is sent, it is assumed that the encrypted file's address will be attached to the outside of an encrypted message using the <strong>file</strong> parameter of the <a href="/method/messages.sendEncryptedFile">messages.sendEncryptedFile</a> method and that the key for direct decryption will be sent in the body of the message (the <strong>key</strong> parameter in the constructors <a href="/constructor/decryptedMessageMediaPhoto">decryptedMessageMediaPhoto</a>, <a href="/constructor/decryptedMessageMediaPhoto">decryptedMessageMediaVideo</a> and <a href="/constructor/decryptedMessageMediaPhoto">decryptedMessageMediaFile</a>.</p>
|
||||
<p>Prior to a file being sent to a secret chat, 2 random 256-bit numbers are computed which will serve as the AES key and initialization vector used to encrypt the file. AES-256 encryption with infinite garble extension (IGE) is used in like manner.</p>
|
||||
<p>The key fingerprint is computed as follows:</p>
|
||||
<ul>
|
||||
<li>digest = md5(key + iv)</li>
|
||||
<li>fingerprint = substr(digest, 0, 4) XOR substr(digest, 4, 4)</li>
|
||||
</ul>
|
||||
<p>The encrypted contents of a file are stored on the server in much the same way as those of a <a href="/api/files">file in cloud chats</a>: piece by piece using calls to <a href="/method/upload.saveFilePart">upload.saveFilePart</a>.
|
||||
A subsequent call to <a href="/method/messages.sendEncryptedFile">messages.sendEncryptedFile</a> will assign an identifier to the stored file and send the address together with the message. The recipient will receive an update with <a href="/constructor/encryptedMessage">encryptedMessage</a>, and the <strong>file</strong> parameter will contain file information.</p>
|
||||
<p>The encrypted contents of a file are stored on the server in much the same way as those of a <a href="/api/files">file in cloud chats</a>: piece by piece using calls to <a href="/method/upload.saveFilePart">upload.saveFilePart</a>.<br>A subsequent call to <a href="/method/messages.sendEncryptedFile">messages.sendEncryptedFile</a> will assign an identifier to the stored file and send the address together with the message. The recipient will receive an update with <a href="/constructor/encryptedMessage">encryptedMessage</a>, and the <strong>file</strong> parameter will contain file information.</p>
|
||||
<p>Incoming and outgoing encrypted files can be forwarded to other secret chats using the constructor <a href="/constructor/inputEncryptedFile">inputEncryptedFile</a> to avoid saving the same content on the server twice.</p>
|
||||
<h4><a class="anchor" href="#working-with-an-update-box" id="working-with-an-update-box" name="working-with-an-update-box"><i class="anchor-icon"></i></a>Working with an Update Box</h4>
|
||||
<p>Secret chats are associated with specific devices (or rather with <a href="/mtproto/description#creating-an-authorization-key">authorization keys</a>), not users. A conventional message box, which uses <strong>pts</strong> to describe the client's status, is not suitable, because it is designed for long-term message storage and message access from different devices.</p>
|
||||
<h4><a class="anchor" name="working-with-an-update-box" href="#working-with-an-update-box"><i class="anchor-icon"></i></a>Working with an Update Box</h4>
|
||||
<p>Secret chats are associated with specific devices (or rather with <a href="/mtproto/description#creating-an-authorization-key">authorization keys</a>), not users. A conventional message box, which uses <strong>pts</strong> to describe the client's status, is not suitable, because it is designed for long-term message storage and message access from different devices.</p>
|
||||
<p>An additional temporary message queue is introduced as a solution to this problem. When an update regarding a message from a secret chat is sent, a new value of <strong>qts</strong> is sent, which helps reconstruct the difference if there has been a long break in the connection or in case of loss of an update.</p>
|
||||
<p>As the number of events increases, the value of <strong>qts</strong> increases by 1 with each new event. The initial value may not (and will not) be equal to 0.</p>
|
||||
<p>The fact that events from the temporary queue have been received and stored by the client is acknowledged explicitly by a call to the <a href="/method/messages.receivedQueue">messages.receivedQueue</a> method or implicitly by a call to <a href="/method/updates.getDifference">updates.getDifference</a> (the value of <strong>qts</strong> passed, not the final state). All messages acknowledged as delivered by the client, as well as any messages older than 7 days, may (and will) be deleted from the server.</p>
|
||||
<p>Upon de-authorization, the event queue of the corresponding device will be forcibly cleared, and the value of <strong>qts</strong> will become irrelevant.</p>
|
||||
<h2><a class="anchor" href="#updating-to-new-layers" id="updating-to-new-layers" name="updating-to-new-layers"><i class="anchor-icon"></i></a>Updating to new layers</h2>
|
||||
<h2><a class="anchor" name="updating-to-new-layers" href="#updating-to-new-layers"><i class="anchor-icon"></i></a>Updating to new layers</h2>
|
||||
<p>Your client should always store the maximal layer that is known to be supported by the client on the other side of a secret chat. When the secret chat is first created, this value should be initialized to 46. This remote layer value must always be updated immediately after receiving <em>any</em> packet containing information of an upper layer, i.e.:</p>
|
||||
<ul>
|
||||
<li>any secret chat message containing <em>layer_no</em> in its <code>decryptedMessageLayer</code> with <em>layer</em>>=46, or</li>
|
||||
<li>a <a href="/constructor/decryptedMessageActionNotifyLayer">decryptedMessageActionNotifyLayer</a> service message, wrapped as if it were the <a href="/constructor/decryptedMessageService">decryptedMessageService</a> constructor of the obsolete layer 8 (constructor <code>decryptedMessageService#aa48327d</code>).</li>
|
||||
</ul>
|
||||
<h4><a class="anchor" href="#notifying-the-remote-client-about-your-local-layer" id="notifying-the-remote-client-about-your-local-layer" name="notifying-the-remote-client-about-your-local-layer"><i class="anchor-icon"></i></a>Notifying the remote client about your local layer</h4>
|
||||
<h4><a class="anchor" name="notifying-the-remote-client-about-your-local-layer" href="#notifying-the-remote-client-about-your-local-layer"><i class="anchor-icon"></i></a>Notifying the remote client about your local layer</h4>
|
||||
<p>In order to notify the remote client of your local layer, your client must send a message of the <code>decryptedMessageActionNotifyLayer</code> type. This notification must be wrapped in a constructor of an appropriate layer.</p>
|
||||
<p>There are two cases when your client must notify the remote client about its local layer:</p>
|
||||
<ol>
|
||||
<li>As soon as a new secret chat has been created, immediately after the secret key has been successfully exchanged.</li>
|
||||
<li>Immediately after the local client has been updated to support a new secret chat layer. In this case notifications must be sent to <strong>all</strong> currently existing secret chats. Note that this is only necessary when updating to new layers that contain changes in the secret chats implementation (e.g. you don't need to do this when your client is updated from Layer 46 to Layer 47).</li>
|
||||
</ol></div>
|
||||
<li>Immediately after the local client has been updated to support a new secret chat layer. In this case notifications must be sent to <strong>all</strong> currently existing secret chats. Note that this is only necessary when updating to new layers that contain changes in the secret chats implementation (e.g. you don't need to do this when your client is updated from Layer 46 to Layer 47).</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<div class="dev_page_bread_crumbs"><ul class="breadcrumb clearfix"><li><a href="/api" >API</a></li><i class="icon icon-breadcrumb-divider"></i><li><a href="/api/pfs" >Perfect Forward Secrecy</a></li></ul></div>
|
||||
<h1 id="dev_page_title">Perfect Forward Secrecy</h1>
|
||||
|
||||
<div id="dev_page_content"><h5><a class="anchor" href="#related-articles" id="related-articles" name="related-articles"><i class="anchor-icon"></i></a>Related articles</h5>
|
||||
<div id="dev_page_content"><h5><a class="anchor" name="related-articles" href="#related-articles"><i class="anchor-icon"></i></a>Related articles</h5>
|
||||
<p><div class="dev_page_nav_wrap"></p>
|
||||
<ul>
|
||||
<li><a href="/api/end-to-end/pfs">Perfect Forward Secrecy in Secret Chats</a></li>
|
||||
|
@ -65,7 +65,8 @@
|
|||
<p>In order to bind a temporary authorization key to the permanent key the client creates a <a href="/method/auth.bindTempAuthKey#binding-message-contents">special binding message</a> and executes the <a href="/method/auth.bindTempAuthKey">auth.bindTempAuthKey</a> method using <strong>temp_auth_key</strong>. Once <strong>auth.bindTempAuthKey</strong> has been executed successfully, the client may continue using the API as usual; the client must also <a href="/api/invoking#saving-client-info">rewrite client info</a> using <a href="/method/initConnection">initConnection</a> after each binding. Each permanent key may only be bound to <strong>one</strong> temporary key at a time, binding a new temporary key overwrites the previous one.</p>
|
||||
<p>Once the temporary key expires, the client needs to generate a new temporary key using <strong>p_q_inner_data_temp</strong>. Then it needs to re-bind that new temporary key to the initial permanent key. A new key can also be generated in advance, so that the client has a new key ready by the time the old one has expired.</p>
|
||||
<p>For additional security, the client can store the temporary authorization key in RAM only and never save it in persistent storage.</p>
|
||||
<p>A temporary authorization key may expire at any moment before <strong>expires_at</strong>, since such keys are also stored only in the RAM on the server-side. Be prepared to handle resulting MTProto errors correctly (non-existent auth_key_id results in a 404 error).</p></div>
|
||||
<p>A temporary authorization key may expire at any moment before <strong>expires_at</strong>, since such keys are also stored only in the RAM on the server-side. Be prepared to handle resulting MTProto errors correctly (non-existent auth_key_id results in a 404 error).</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -47,8 +47,7 @@ MTProto v.1.0 is deprecated and is currently being phased…">
|
|||
<div id="dev_page_content"><!-- scroll_nav -->
|
||||
|
||||
<blockquote>
|
||||
<p>As of version 4.6, major Telegram clients are using <strong>MTProto 2.0</strong>.
|
||||
MTProto v.1.0 is deprecated and is currently being phased out.</p>
|
||||
<p>As of version 4.6, major Telegram clients are using <strong>MTProto 2.0</strong>.<br>MTProto v.1.0 is deprecated and is currently being phased out.</p>
|
||||
</blockquote>
|
||||
<p>This article describes the basic layer of the MTProto protocol version 2.0 (Cloud chats, server-client encryption). The principal differences from version 1.0 (<a href="/mtproto/description_v1">described here</a> for reference) are as follows:</p>
|
||||
<ul>
|
||||
|
@ -58,17 +57,18 @@ MTProto v.1.0 is deprecated and is currently being phased out.</p>
|
|||
<li>12..1024 padding bytes are used instead of 0..15 padding bytes in v.1.0.</li>
|
||||
</ul>
|
||||
<p>See also: <a href="https://core.telegram.org/api/end-to-end">MTProto 2.0: Secret Chats, end-to-end encryption</a></p>
|
||||
<h3><a class="anchor" href="#protocol-description" id="protocol-description" name="protocol-description"><i class="anchor-icon"></i></a>Protocol description</h3>
|
||||
<h3><a class="anchor" name="protocol-description" href="#protocol-description"><i class="anchor-icon"></i></a>Protocol description</h3>
|
||||
<p>Before a message (or a multipart message) is transmitted over a network using a transport protocol, it is encrypted in a certain way, and an external header is added at the top of the message that consists of a 64-bit key identifier <strong>auth_key_id</strong> (that uniquely identifies an authorization key for the server as well as the user) and a 128-bit message key <strong>msg_key</strong>. </p>
|
||||
<p>The authorization key <strong>auth_key</strong> combined with the message key <strong>msg_key</strong> define an actual 256-bit key <strong>aes_key</strong> and a 256-bit initialization vector <strong>aes_iv</strong>, which are used to encrypt the message using AES-256 encryption in infinite garble extension (IGE) mode. Note that the initial part of the message to be encrypted contains variable data (session, message ID, sequence number, server salt) that obviously influences the message key (and thus the AES key and iv). In <strong>MTProto 2.0</strong>, the message key is defined as the 128 middle bits of the SHA-256 of the message body (including session, message ID, padding, etc.) prepended by 32 bytes taken from the authorization key. In the older <strong>MTProto 1.0</strong>, the message key was computed as the lower 128 bits of SHA-1 of the message body, excluding the padding bytes.</p>
|
||||
<p>Multipart messages are encrypted as a single message. </p>
|
||||
<div><a href="/file/811140746/2/CzMyJPVnPo8.81605/c2310d6ede1a5e220f">
|
||||
<img src="/file/811140746/2/CzMyJPVnPo8.81605/c2310d6ede1a5e220f" alt="MTProto server-client encryption, cloud chats" class="dev_page_image" style="max-width: 600px;">
|
||||
<img src="/file/811140746/2/CzMyJPVnPo8.81605/c2310d6ede1a5e220f" alt="MTProto server-client encryption, cloud chats" class="dev_page_image" style="max-width: 600px;" />
|
||||
</a></div>
|
||||
|
||||
<blockquote>
|
||||
<p>Got questions about this setup? — Check out the <a href="http://core.telegram.org/techfaq">Advanced FAQ</a>!</p>
|
||||
</blockquote>
|
||||
<h6><strong>Note 1</strong></h6>
|
||||
<h6><a class="anchor" name="note-1" href="#note-1"><i class="anchor-icon"></i></a><strong>Note 1</strong></h6>
|
||||
<p>Each plaintext message to be encrypted in MTProto always contains the following data to be checked upon decryption in order to make the system robust against known problems with the components:</p>
|
||||
<ul>
|
||||
<li>server salt (64-Bit)</li>
|
||||
|
@ -77,39 +77,39 @@ MTProto v.1.0 is deprecated and is currently being phased out.</p>
|
|||
<li>message length</li>
|
||||
<li>time</li>
|
||||
</ul>
|
||||
<h6><strong>Note 2</strong></h6>
|
||||
<p>Telegram's <strong>End-to-end</strong> encrypted Secret Chats are using an additional layer of encryption on top of the described above. See <a href="https://core.telegram.org/api/end-to-end">Secret Chats, End-to-End encryption</a> for details.</p>
|
||||
<h6><a class="anchor" name="note-2" href="#note-2"><i class="anchor-icon"></i></a><strong>Note 2</strong></h6>
|
||||
<p>Telegram's <strong>End-to-end</strong> encrypted Secret Chats are using an additional layer of encryption on top of the described above. See <a href="https://core.telegram.org/api/end-to-end">Secret Chats, End-to-End encryption</a> for details.</p>
|
||||
<blockquote>
|
||||
<p>MTProto supports <a href="https://core.telegram.org/api/pfs">Perfect Forward Secrecy</a> in both <a href="https://core.telegram.org/api/pfs">cloud chats</a> and <a href="https://core.telegram.org/api/end-to-end/pfs">secret chats</a>.</p>
|
||||
</blockquote>
|
||||
<h3><a class="anchor" href="#terminology" id="terminology" name="terminology"><i class="anchor-icon"></i></a>Terminology</h3>
|
||||
<h4><a class="anchor" href="#authorization-key-auth-key" id="authorization-key-auth-key" name="authorization-key-auth-key"><i class="anchor-icon"></i></a>Authorization Key (auth_key)</h4>
|
||||
<h3><a class="anchor" name="terminology" href="#terminology"><i class="anchor-icon"></i></a>Terminology</h3>
|
||||
<h4><a class="anchor" name="authorization-key-auth-key" href="#authorization-key-auth-key"><i class="anchor-icon"></i></a>Authorization Key (auth_key)</h4>
|
||||
<p>A 2048-bit key shared by the client device and the server, created upon user registration directly on the client device by exchanging Diffie-Hellman keys, and never transmitted over a network. Each authorization key is user-specific. There is nothing that prevents a user from having several keys (that correspond to “permanent sessions” on different devices), and some of these may be locked forever in the event the device is lost. See also <a href="/mtproto/auth_key">Creating an Authorization Key</a>.</p>
|
||||
<h4><a class="anchor" href="#server-key" id="server-key" name="server-key"><i class="anchor-icon"></i></a>Server Key</h4>
|
||||
<h4><a class="anchor" name="server-key" href="#server-key"><i class="anchor-icon"></i></a>Server Key</h4>
|
||||
<p>A 2048-bit RSA key used by the server digitally to sign its own messages while registration is underway and the authorization key is being generated. The application has a built-in public server key which can be used to verify a signature but cannot be used to sign messages. A private server key is stored on the server and changed very infrequently.</p>
|
||||
<h4><a class="anchor" href="#key-identifier-auth-key-id" id="key-identifier-auth-key-id" name="key-identifier-auth-key-id"><i class="anchor-icon"></i></a>Key Identifier (auth_key_id)</h4>
|
||||
<h4><a class="anchor" name="key-identifier-auth-key-id" href="#key-identifier-auth-key-id"><i class="anchor-icon"></i></a>Key Identifier (auth_key_id)</h4>
|
||||
<p>The 64 lower-order bits of the SHA1 hash of the authorization key are used to indicate which particular key was used to encrypt a message. Keys must be uniquely defined by the 64 lower-order bits of their SHA1, and in the event of a collision, an authorization key is regenerated. A zero key identifier means that encryption is not used which is permissible for a limited set of message types used during registration to generate an authorization key in a Diffie-Hellman exchange. <strong>For MTProto 2.0, SHA1 is still used here, because auth_key_id should identify the authorization key used independently of the protocol version.</strong></p>
|
||||
<h4><a class="anchor" href="#session" id="session" name="session"><i class="anchor-icon"></i></a>Session</h4>
|
||||
<h4><a class="anchor" name="session" href="#session"><i class="anchor-icon"></i></a>Session</h4>
|
||||
<p>A (random) 64-bit number generated by the client to distinguish between individual sessions (for example, between different instances of the application, created with the same authorization key). The session in conjunction with the key identifier corresponds to an application instance. The server can maintain session state. <em>Under no circumstances can a message meant for one session be sent into a different session</em>. The server may unilaterally forget any client sessions; clients should be able to handle this. </p>
|
||||
<h4><a class="anchor" href="#server-salt" id="server-salt" name="server-salt"><i class="anchor-icon"></i></a>Server Salt</h4>
|
||||
<h4><a class="anchor" name="server-salt" href="#server-salt"><i class="anchor-icon"></i></a>Server Salt</h4>
|
||||
<p>A (random) 64-bit number changed every 30 minutes (separately for each session) at the request of the server. All subsequent messages must contain the new salt (although, messages with the old salt are still accepted for a further 1800 seconds). Required to protect against replay attacks and certain tricks associated with adjusting the client clock to a moment in the distant future.</p>
|
||||
<h4><a class="anchor" href="#message-identifier-msg-id" id="message-identifier-msg-id" name="message-identifier-msg-id"><i class="anchor-icon"></i></a>Message Identifier (msg_id)</h4>
|
||||
<h4><a class="anchor" name="message-identifier-msg-id" href="#message-identifier-msg-id"><i class="anchor-icon"></i></a>Message Identifier (msg_id)</h4>
|
||||
<p>A (time-dependent) 64-bit number used uniquely to identify a message within a session. Client message identifiers are divisible by 4, server message identifiers modulo 4 yield 1 if the message is a response to a client message, and 3 otherwise. Client message identifiers must increase monotonically (within a single session), the same as server message identifiers, and must approximately equal unixtime*2^32. This way, a message identifier points to the approximate moment in time the message was created. A message is rejected over 300 seconds after it is created or 30 seconds before it is created (this is needed to protect from replay attacks). In this situation, it must be re-sent with a different identifier (or placed in a container with a higher identifier). The identifier of a message container must be strictly greater than those of its nested messages.</p>
|
||||
<p><strong>Important</strong>: to counter replay-attacks the lower 32 bits of <strong>msg_id</strong> passed by the client must not be empty and must present a fractional part of the time point when the message was created.</p>
|
||||
<h4><a class="anchor" href="#content-related-message" id="content-related-message" name="content-related-message"><i class="anchor-icon"></i></a>Content-related Message</h4>
|
||||
<h4><a class="anchor" name="content-related-message" href="#content-related-message"><i class="anchor-icon"></i></a>Content-related Message</h4>
|
||||
<p>A message requiring an explicit acknowledgment. These include all the user and many service messages, virtually all with the exception of containers and acknowledgments. </p>
|
||||
<h4><a class="anchor" href="#message-sequence-number-msg-seqno" id="message-sequence-number-msg-seqno" name="message-sequence-number-msg-seqno"><i class="anchor-icon"></i></a>Message Sequence Number (msg_seqno)</h4>
|
||||
<h4><a class="anchor" name="message-sequence-number-msg-seqno" href="#message-sequence-number-msg-seqno"><i class="anchor-icon"></i></a>Message Sequence Number (msg_seqno)</h4>
|
||||
<p>A 32-bit number equal to twice the number of “content-related” messages (those requiring acknowledgment, and in particular those that are not containers) created by the sender prior to this message and subsequently incremented by one if the current message is a content-related message. A container is always generated after its entire contents; therefore, its sequence number is greater than or equal to the sequence numbers of the messages contained in it.</p>
|
||||
<h4><a class="anchor" href="#message-key-msg-key" id="message-key-msg-key" name="message-key-msg-key"><i class="anchor-icon"></i></a>Message Key (msg_key)</h4>
|
||||
<h4><a class="anchor" name="message-key-msg-key" href="#message-key-msg-key"><i class="anchor-icon"></i></a>Message Key (msg_key)</h4>
|
||||
<p>In <strong>MTProto 2.0</strong>, the middle 128 bits of the SHA-256 hash of the message to be encrypted (including the internal header and the <em>padding bytes</em> for MTProto 2.0), prepended by a 32-byte fragment of the authorization key.</p>
|
||||
<p>In <strong>MTProto 1.0</strong>, message key was defined differently, as the lower 128 bits of the SHA-1 hash of the message to be encrypted, with padding bytes excluded from the computation of the hash. Authorization key was not involved in this computation.</p>
|
||||
<h4><a class="anchor" href="#internal-cryptographic-header" id="internal-cryptographic-header" name="internal-cryptographic-header"><i class="anchor-icon"></i></a>Internal (cryptographic) Header</h4>
|
||||
<h4><a class="anchor" name="internal-cryptographic-header" href="#internal-cryptographic-header"><i class="anchor-icon"></i></a>Internal (cryptographic) Header</h4>
|
||||
<p>A header (16 bytes) added before a message or a container before it is all encrypted together. Consists of the server salt (64 bits) and the session (64 bits).</p>
|
||||
<h4><a class="anchor" href="#external-cryptographic-header" id="external-cryptographic-header" name="external-cryptographic-header"><i class="anchor-icon"></i></a>External (cryptographic) Header</h4>
|
||||
<h4><a class="anchor" name="external-cryptographic-header" href="#external-cryptographic-header"><i class="anchor-icon"></i></a>External (cryptographic) Header</h4>
|
||||
<p>A header (24 bytes) added before an encrypted message or a container. Consists of the key identifier <strong>auth_key_id</strong> (64 bits) and the message key <strong>msg_key</strong> (128 bits).</p>
|
||||
<h4><a class="anchor" href="#payload" id="payload" name="payload"><i class="anchor-icon"></i></a>Payload</h4>
|
||||
<h4><a class="anchor" name="payload" href="#payload"><i class="anchor-icon"></i></a>Payload</h4>
|
||||
<p>External header + encrypted message or container.</p>
|
||||
<h3><a class="anchor" href="#defining-aes-key-and-initialization-vector" id="defining-aes-key-and-initialization-vector" name="defining-aes-key-and-initialization-vector"><i class="anchor-icon"></i></a>Defining AES Key and Initialization Vector</h3>
|
||||
<h3><a class="anchor" name="defining-aes-key-and-initialization-vector" href="#defining-aes-key-and-initialization-vector"><i class="anchor-icon"></i></a>Defining AES Key and Initialization Vector</h3>
|
||||
<p>The 2048-bit authorization key (auth_key) and the 128-bit message key (msg_key) are used to compute a 256-bit AES key (aes_key) and a 256-bit initialization vector (aes_iv) which are subsequently used to encrypt the part of the message to be encrypted (i. e. everything with the exception of the external header that is added later) with AES-256 in infinite garble extension (IGE) mode.</p>
|
||||
<p>For MTProto 2.0, the algorithm for computing aes_key and aes_iv from auth_key and msg_key is as follows.</p>
|
||||
<ul>
|
||||
|
@ -124,48 +124,52 @@ MTProto v.1.0 is deprecated and is currently being phased out.</p>
|
|||
<p><em>For the obsolete MTProto 1.0, msg_key, aes_key, and aes_iv were computed differently (see <a href="/mtproto/description_v1#defining-aes-key-and-initialization-vector">this document</a> for reference).</em></p>
|
||||
<p>The lower-order 1024 bits of auth_key are not involved in the computation. They may (together with the remaining bits or separately) be used on the client device to encrypt the local copy of the data received from the server. The 512 lower-order bits of auth_key are not stored on the server; therefore, if the client device uses them to encrypt local data and the user loses the key or the password, data decryption of local data is impossible (even if data from the server could be obtained).</p>
|
||||
<p>In MTProto 1.0, when AES was used to encrypt a block of data of a length not divisible by 16 bytes, the data was padded with 0 to 15 random padding bytes <strong>random_padding</strong> to a length divisible by 16 bytes prior to encryption. <strong>In MTProto 2.0, this padding is taken into account when computing <code>msg_key</code>. Note that MTProto 2.0 requires from 12 to 1024 bytes of padding, still subject to the condition that the resulting message length be divisible by 16 bytes.</strong></p>
|
||||
<h3><a class="anchor" href="#using-mtproto-20-instead-of-mtproto-10" id="using-mtproto-20-instead-of-mtproto-10" name="using-mtproto-20-instead-of-mtproto-10"><i class="anchor-icon"></i></a>Using MTProto 2.0 instead of MTProto 1.0</h3>
|
||||
<h3><a class="anchor" name="using-mtproto-2-0-instead-of-mtproto-1-0" href="#using-mtproto-2-0-instead-of-mtproto-1-0"><i class="anchor-icon"></i></a>Using MTProto 2.0 instead of MTProto 1.0</h3>
|
||||
<p>A client may either use only MTProto 2.0 or only MTProto 1.0 in the same TCP connection. The server detects the protocol used by the first message received from the client, and then uses the same encryption for its messages, and expects the client to use the same encryption henceforth. We recommend using MTProto 2.0; MTProto 1.0 is deprecated and supported for backward compatibility only.</p>
|
||||
<h3><a class="anchor" href="#important-checks" id="important-checks" name="important-checks"><i class="anchor-icon"></i></a>Important Checks</h3>
|
||||
<h3><a class="anchor" name="important-checks" href="#important-checks"><i class="anchor-icon"></i></a>Important Checks</h3>
|
||||
<p>When an encrypted message is received, it <em>must</em> be checked that <strong>msg_key</strong> is <em>in fact</em> equal to the 128 middle bits of the SHA-256 of the decrypted data with a 32-byte fragment of <strong>auth_key</strong> prepended to it, and that msg_id has even parity for messages from client to server, and odd parity for messages from server to client.</p>
|
||||
<p>In addition, the identifiers (msg_id) of the last N messages received from the other side must be stored, and if a message comes in with msg_id lower than all or equal to any of the stored values, the message is to be ignored. Otherwise, the new message msg_id is added to the set, and, if the number of stored msg_id values is greater than N, the oldest (i. e. the lowest) is forgotten.</p>
|
||||
<p>On top of this, msg_id values that belong over 30 seconds in the future or over 300 seconds in the past are to be ignored. This is especially important for the server. The client would also find this useful (to protect from a replay attack), but only if it is certain of its time (for example, if its time has been synchronized with that of the server).</p>
|
||||
<p>Certain client-to-server service messages containing data sent by the client to the server (for example, msg_id of a recent client query) may, nonetheless, be processed on the client even if the time appears to be “incorrect”. This is especially true of messages to change server_salt and notifications of invalid client time. See <a href="/mtproto/service_messages">Mobile Protocol: Service Messages</a>.</p>
|
||||
<h3><a class="anchor" href="#storing-an-authorization-key-on-a-client-device" id="storing-an-authorization-key-on-a-client-device" name="storing-an-authorization-key-on-a-client-device"><i class="anchor-icon"></i></a>Storing an Authorization Key on a Client Device</h3>
|
||||
<p>It may be suggested to users concerned with security that they password protect the authorization key in approximately the same way as in ssh. This can be accomplished by prepending the value of a cryptographic hash function, such as SHA-256, of the key to the front of the key, following which the entire string is encrypted using AES in CBC mode and a key equal to the user's (text) password. When the user inputs the password, the stored protected password is decrypted and verified by checking the SHA-256 value. From the user's standpoint, this is practically the same as using an application or a website password.</p>
|
||||
<h3><a class="anchor" href="#unencrypted-messages" id="unencrypted-messages" name="unencrypted-messages"><i class="anchor-icon"></i></a>Unencrypted Messages</h3>
|
||||
<h3><a class="anchor" name="storing-an-authorization-key-on-a-client-device" href="#storing-an-authorization-key-on-a-client-device"><i class="anchor-icon"></i></a>Storing an Authorization Key on a Client Device</h3>
|
||||
<p>It may be suggested to users concerned with security that they password protect the authorization key in approximately the same way as in ssh. This can be accomplished by prepending the value of a cryptographic hash function, such as SHA-256, of the key to the front of the key, following which the entire string is encrypted using AES in CBC mode and a key equal to the user's (text) password. When the user inputs the password, the stored protected password is decrypted and verified by checking the SHA-256 value. From the user's standpoint, this is practically the same as using an application or a website password.</p>
|
||||
<h3><a class="anchor" name="unencrypted-messages" href="#unencrypted-messages"><i class="anchor-icon"></i></a>Unencrypted Messages</h3>
|
||||
<p>Special plain-text messages may be used to create an authorization key as well as to perform a time synchronization. They begin with auth_key_id = 0 (64 bits) which means that there is no auth_key. This is followed directly by the message body in serialized format without internal or external headers. A message identifier (64 bits) and body length in bytes (32 bytes) are added before the message body.</p>
|
||||
<p>Only a very limited number of messages of special types can be transmitted as plain text. </p>
|
||||
<h3><a class="anchor" href="#schematic-presentation-of-messages" id="schematic-presentation-of-messages" name="schematic-presentation-of-messages"><i class="anchor-icon"></i></a>Schematic Presentation of Messages</h3>
|
||||
<h4><a class="anchor" href="#encrypted-message" id="encrypted-message" name="encrypted-message"><i class="anchor-icon"></i></a>Encrypted Message</h4>
|
||||
<table class="table"><tr>
|
||||
<td><a href="#key-identifier-auth-key-id"><strong>auth_key_id</strong></a><br>int64</td>
|
||||
<td><a href="#message-key-msg-key"><strong>msg_key</strong></a><br>int128</td>
|
||||
<td><a href="#encrypted-message-encrypted-data"><strong>encrypted_data</strong></a><br>bytes</td>
|
||||
<h3><a class="anchor" name="schematic-presentation-of-messages" href="#schematic-presentation-of-messages"><i class="anchor-icon"></i></a>Schematic Presentation of Messages</h3>
|
||||
<h4><a class="anchor" name="encrypted-message" href="#encrypted-message"><i class="anchor-icon"></i></a>Encrypted Message</h4>
|
||||
<table class="table table-bordered table-msg-schema"><tr>
|
||||
<td><a href="#key-identifier-auth-key-id"><strong>auth_key_id</strong></a><br/>int64</td>
|
||||
<td><a href="#message-key-msg-key"><strong>msg_key</strong></a><br/>int128</td>
|
||||
<td><a href="#encrypted-message-encrypted-data"><strong>encrypted_data</strong></a><br/>bytes</td>
|
||||
</tr></table>
|
||||
<h4><a class="anchor" href="#encrypted-message-encrypted-data" id="encrypted-message-encrypted-data" name="encrypted-message-encrypted-data"><i class="anchor-icon"></i></a>Encrypted Message: <em>encrypted_data</em></h4>
|
||||
|
||||
<h4><a class="anchor" name="encrypted-message-encrypted-data" href="#encrypted-message-encrypted-data"><i class="anchor-icon"></i></a>Encrypted Message: <em>encrypted_data</em></h4>
|
||||
<p>Contains the cypher text for the following data:</p>
|
||||
<table class="table"><tr>
|
||||
<td><a href="#server-salt"><strong>salt</strong></a><br>int64</td>
|
||||
<td><a href="#session"><strong>session_id</strong></a><br>int64</td>
|
||||
<td><a href="#message-identifier-msg-id"><strong>message_id</strong></a><br>int64</td>
|
||||
<td><a href="#message-sequence-number-msg-seqno"><strong>seq_no</strong></a><br>int32</td>
|
||||
<td><strong>message_data_length</strong><br>int32</td>
|
||||
<td><strong>message_data</strong><br>bytes</td>
|
||||
<td><strong>padding</strong>12..1024<br>bytes</td>
|
||||
<table class="table table-bordered table-msg-schema"><tr>
|
||||
<td><a href="#server-salt"><strong>salt</strong></a><br/>int64</td>
|
||||
<td><a href="#session"><strong>session_id</strong></a><br/>int64</td>
|
||||
<td><a href="#message-identifier-msg-id"><strong>message_id</strong></a><br/>int64</td>
|
||||
<td><a href="#message-sequence-number-msg-seqno"><strong>seq_no</strong></a><br/>int32</td>
|
||||
<td><strong>message_data_length</strong><br/>int32</td>
|
||||
<td><strong>message_data</strong><br/>bytes</td>
|
||||
<td><strong>padding</strong>12..1024<br/>bytes</td>
|
||||
</tr></table>
|
||||
<h4><a class="anchor" href="#unencrypted-message" id="unencrypted-message" name="unencrypted-message"><i class="anchor-icon"></i></a>Unencrypted Message</h4>
|
||||
<table class="table"><tr>
|
||||
<td><a href="#key-identifier-auth-key-id"><strong>auth_key_id</strong></a> = <code>0</code><br>int64</td>
|
||||
<td><a href="#message-identifier-msg-id"><strong>message_id</strong></a><br>int64</td>
|
||||
<td><strong>message_data_length</strong><br>int32</td>
|
||||
<td><strong>message_data</strong><br>bytes</td>
|
||||
|
||||
<h4><a class="anchor" name="unencrypted-message" href="#unencrypted-message"><i class="anchor-icon"></i></a>Unencrypted Message</h4>
|
||||
<table class="table table-bordered table-msg-schema"><tr>
|
||||
<td><a href="#key-identifier-auth-key-id"><strong>auth_key_id</strong></a> = <code>0</code><br/>int64</td>
|
||||
<td><a href="#message-identifier-msg-id"><strong>message_id</strong></a><br/>int64</td>
|
||||
<td><strong>message_data_length</strong><br/>int32</td>
|
||||
<td><strong>message_data</strong><br/>bytes</td>
|
||||
</tr></table>
|
||||
|
||||
<p><strong>MTProto 2.0 uses 12..1024 padding bytes, instead of the 0..15 used in MTProto 1.0</strong></p>
|
||||
<h3><a class="anchor" href="#creating-an-authorization-key" id="creating-an-authorization-key" name="creating-an-authorization-key"><i class="anchor-icon"></i></a>Creating an Authorization Key</h3>
|
||||
<h3><a class="anchor" name="creating-an-authorization-key" href="#creating-an-authorization-key"><i class="anchor-icon"></i></a>Creating an Authorization Key</h3>
|
||||
<p>An authorization key is normally created once for every user during the application installation process immediately prior to registration. Registration itself, in actuality, occurs after the authorization key is created. However, a user may be prompted to complete the registration form while the authorization key is being generated in the background. Intervals between user key strokes may be used as a source of entropy in the generation of high-quality random numbers required for the creation of an authorization key.</p>
|
||||
<p>See <a href="/mtproto/auth_key">Creating an Authorization Key</a>.</p>
|
||||
<p>During the creation of the authorization key, the client obtains its server salt (to be used with the new key for all communication in the near future). The client then creates an encrypted session using the newly generated key, and subsequent communication occurs within that session (including the transmission of the user's registration information and phone number validation) unless the client creates a new session. The client is free to create new or additional sessions at any time by choosing a new random session_id.</p></div>
|
||||
<p>During the creation of the authorization key, the client obtains its server salt (to be used with the new key for all communication in the near future). The client then creates an encrypted session using the newly generated key, and subsequent communication occurs within that session (including the transmission of the user's registration information and phone number validation) unless the client creates a new session. The client is free to create new or additional sessions at any time by choosing a new random session_id.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in a new issue