Skip to main content

grammers_crypto/
lib.rs

1// Copyright 2020 - developers of the `grammers` project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! This library contains a collection of functions that relate to
10//! encrypting and decryption values when exchanging messages with Telegram.
11
12#![deny(unsafe_code)]
13
14pub mod aes;
15mod auth_key;
16mod deque_buffer;
17mod factorize;
18pub mod hex;
19mod obfuscated;
20pub mod rsa;
21mod sha;
22pub mod two_factor_auth;
23
24use std::fmt;
25
26pub use auth_key::AuthKey;
27pub use deque_buffer::DequeBuffer;
28pub use factorize::factorize;
29pub use obfuscated::ObfuscatedCipher;
30
31/// The error type for [`decrypt_data_v2`].
32#[derive(Clone, Debug, PartialEq)]
33pub enum Error {
34    /// The ciphertext is either too small or not padded correctly.
35    InvalidBuffer,
36
37    /// The server replied with the ID of a different authorization key.
38    AuthKeyMismatch,
39
40    /// The key of the message did not match our expectations.
41    MessageKeyMismatch,
42}
43
44impl std::error::Error for Error {}
45
46impl fmt::Display for Error {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        match *self {
49            Error::InvalidBuffer => write!(f, "invalid ciphertext buffer length"),
50            Error::AuthKeyMismatch => write!(f, "server authkey mismatches with ours"),
51            Error::MessageKeyMismatch => write!(f, "server msgkey mismatches with ours"),
52        }
53    }
54}
55
56enum Side {
57    Client,
58    Server,
59}
60
61impl Side {
62    // "where x = 0 for messages from client to server and x = 8 for those from server to client."
63    fn x(&self) -> usize {
64        match *self {
65            Side::Client => 0,
66            Side::Server => 8,
67        }
68    }
69}
70
71/// Calculate the key based on Telegram [guidelines for MTProto 2],
72/// returning the pair `(key, iv)` for use in AES-IGE mode.
73///
74/// [guidelines for MTProto 2]: https://core.telegram.org/mtproto/description#defining-aes-key-and-initialization-vector
75fn calc_key(auth_key: &AuthKey, msg_key: &[u8; 16], side: Side) -> ([u8; 32], [u8; 32]) {
76    let x = side.x();
77
78    // sha256_a = SHA256 (msg_key + substr (auth_key, x, 36));
79    let sha256_a = sha256!(msg_key, &auth_key.data[x..x + 36]);
80
81    // sha256_b = SHA256 (substr (auth_key, 40+x, 36) + msg_key);
82    let sha256_b = sha256!(&auth_key.data[40 + x..40 + x + 36], msg_key);
83
84    // aes_key = substr (sha256_a, 0, 8) + substr (sha256_b, 8, 16) + substr (sha256_a, 24, 8);
85    let aes_key = {
86        let mut buffer = [0; 32];
87        buffer[0..8].copy_from_slice(&sha256_a[0..8]);
88        buffer[8..8 + 16].copy_from_slice(&sha256_b[8..8 + 16]);
89        buffer[24..24 + 8].copy_from_slice(&sha256_a[24..24 + 8]);
90        buffer
91    };
92
93    // aes_iv = substr (sha256_b, 0, 8) + substr (sha256_a, 8, 16) + substr (sha256_b, 24, 8);
94    let aes_iv = {
95        let mut buffer = [0; 32];
96        buffer[0..8].copy_from_slice(&sha256_b[0..8]);
97        buffer[8..8 + 16].copy_from_slice(&sha256_a[8..8 + 16]);
98        buffer[24..24 + 8].copy_from_slice(&sha256_b[24..24 + 8]);
99        buffer
100    };
101
102    (aes_key, aes_iv)
103}
104
105/// Determines the padding length needed for a plaintext of a certain length,
106/// according to the following citation:
107///
108/// > Note that MTProto 2.0 requires from 12 to 1024 bytes of padding
109/// > [...] the resulting message length be divisible by 16 bytes
110fn determine_padding_v2_length(len: usize) -> usize {
111    16 + (16 - (len % 16))
112}
113
114// Inner body of `encrypt_data_v2`, separated for testing purposes.
115fn do_encrypt_data_v2(buffer: &mut DequeBuffer<u8>, auth_key: &AuthKey, random_padding: &[u8; 32]) {
116    // "Note that MTProto 2.0 requires from 12 to 1024 bytes of padding"
117    // "[...] the resulting message length be divisible by 16 bytes"
118    let padding_len = determine_padding_v2_length(buffer.len());
119    buffer.extend(random_padding.iter().take(padding_len));
120
121    // Encryption is done by the client
122    let side = Side::Client;
123    let x = side.x();
124
125    // msg_key_large = SHA256 (substr (auth_key, 88+x, 32) + plaintext + random_padding);
126    let msg_key_large = sha256!(&auth_key.data[88 + x..88 + x + 32], &buffer[..]);
127
128    // msg_key = substr (msg_key_large, 8, 16);
129    let msg_key = {
130        let mut buffer = [0; 16];
131        buffer.copy_from_slice(&msg_key_large[8..8 + 16]);
132        buffer
133    };
134
135    // Calculate the key
136    let (key, iv) = calc_key(auth_key, &msg_key, side);
137
138    aes::ige_encrypt(&mut buffer[..], &key, &iv);
139
140    buffer.extend_front(&msg_key);
141    buffer.extend_front(&auth_key.key_id);
142}
143
144/// This function implements the [MTProto 2.0 algorithm] for computing
145/// `aes_key` and `aes_iv` from `auth_key` and `msg_key` as specified
146///
147/// [MTProto 2.0 algorithm]: https://core.telegram.org/mtproto/description#defining-aes-key-and-initialization-vector
148pub fn encrypt_data_v2(buffer: &mut DequeBuffer<u8>, auth_key: &AuthKey) {
149    let random_padding = {
150        let mut rnd = [0; 32];
151        getrandom::fill(&mut rnd).expect("failed to generate a secure padding");
152        rnd
153    };
154
155    do_encrypt_data_v2(buffer, auth_key, &random_padding)
156}
157
158/// This method is the inverse of `encrypt_data_v2`.
159/// Returns the slice of the input buffer that contains the decrypted plaintext.
160pub fn decrypt_data_v2<'b>(
161    buffer: &'b mut [u8],
162    auth_key: &AuthKey,
163) -> Result<&'b mut [u8], Error> {
164    // Decryption is done from the server
165    let side = Side::Server;
166    let x = side.x();
167
168    if buffer.len() < 24 || (buffer.len() - 24) % 16 != 0 {
169        return Err(Error::InvalidBuffer);
170    }
171
172    // TODO Check salt, session_id and sequence_number
173    let key_id = &buffer[..8];
174    if auth_key.key_id != *key_id {
175        return Err(Error::AuthKeyMismatch);
176    }
177
178    let mut msg_key = [0; 16];
179    msg_key.copy_from_slice(&buffer[8..8 + 16]);
180
181    let (key, iv) = calc_key(auth_key, &msg_key, Side::Server);
182
183    aes::ige_decrypt(&mut buffer[8 + 16..], &key, &iv);
184    let plaintext = &buffer[8 + 16..];
185
186    // https://core.telegram.org/mtproto/security_guidelines#mtproto-encrypted-messages
187    let our_key = sha256!(&auth_key.data[88 + x..88 + x + 32], &plaintext);
188
189    if msg_key != our_key[8..8 + 16] {
190        return Err(Error::MessageKeyMismatch);
191    }
192
193    Ok(&mut buffer[8 + 16..])
194}
195
196/// Generate the AES key and initialization vector from the server nonce
197/// and the new client nonce. This is done after the DH exchange.
198pub fn generate_key_data_from_nonce(
199    server_nonce: &[u8; 16],
200    new_nonce: &[u8; 32],
201) -> ([u8; 32], [u8; 32]) {
202    let hash1 = sha1!(new_nonce, server_nonce);
203    let hash2 = sha1!(server_nonce, new_nonce);
204    let hash3 = sha1!(new_nonce, new_nonce);
205
206    // key = hash1 + hash2[:12]
207    let key = {
208        let mut buffer = [0; 32];
209        buffer[..hash1.len()].copy_from_slice(&hash1);
210        buffer[hash1.len()..].copy_from_slice(&hash2[..12]);
211        buffer
212    };
213
214    // iv = hash2[12:20] + hash3 + new_nonce[:4]
215    let iv = {
216        let mut buffer = [0; 32];
217        buffer[..8].copy_from_slice(&hash2[12..]);
218        buffer[8..28].copy_from_slice(&hash3);
219        buffer[28..].copy_from_slice(&new_nonce[..4]);
220        buffer
221    };
222
223    (key, iv)
224}
225
226#[cfg(test)]
227mod tests {
228    use super::*;
229
230    fn get_test_auth_key() -> AuthKey {
231        let mut buffer = [0u8; 256];
232        buffer
233            .iter_mut()
234            .enumerate()
235            .for_each(|(i, x)| *x = i as u8);
236
237        AuthKey::from_bytes(buffer)
238    }
239
240    fn get_test_msg_key() -> [u8; 16] {
241        let mut buffer = [0u8; 16];
242        buffer
243            .iter_mut()
244            .enumerate()
245            .for_each(|(i, x)| *x = i as u8);
246
247        buffer
248    }
249
250    fn get_test_aes_key_or_iv() -> [u8; 32] {
251        let mut buffer = [0u8; 32];
252        buffer
253            .iter_mut()
254            .enumerate()
255            .for_each(|(i, x)| *x = i as u8);
256
257        buffer
258    }
259
260    #[test]
261    fn calc_client_key() {
262        let auth_key = get_test_auth_key();
263        let msg_key = get_test_msg_key();
264        let expected = (
265            [
266                112, 78, 208, 156, 139, 65, 102, 138, 232, 249, 157, 36, 71, 56, 247, 29, 189, 220,
267                68, 70, 155, 107, 189, 74, 168, 87, 61, 208, 66, 189, 5, 158,
268            ],
269            [
270                77, 38, 96, 0, 165, 80, 237, 171, 191, 76, 124, 228, 15, 208, 4, 60, 201, 34, 48,
271                24, 76, 211, 23, 165, 204, 156, 36, 130, 253, 59, 147, 24,
272            ],
273        );
274        assert_eq!(calc_key(&auth_key, &msg_key, Side::Client), expected);
275    }
276
277    #[test]
278    fn calc_server_key() {
279        let auth_key = get_test_auth_key();
280        let msg_key = get_test_msg_key();
281        let expected = (
282            [
283                33, 119, 37, 121, 155, 36, 88, 6, 69, 129, 116, 161, 252, 251, 200, 131, 144, 104,
284                7, 177, 80, 51, 253, 208, 234, 43, 77, 105, 207, 156, 54, 78,
285            ],
286            [
287                102, 154, 101, 56, 145, 122, 79, 165, 108, 163, 35, 96, 164, 49, 201, 22, 11, 228,
288                173, 136, 113, 64, 152, 13, 171, 145, 206, 123, 220, 71, 255, 188,
289            ],
290        );
291        assert_eq!(calc_key(&auth_key, &msg_key, Side::Server), expected);
292    }
293
294    #[test]
295    fn encrypt_client_data_v2() {
296        let mut buffer = DequeBuffer::with_capacity(0, 0);
297        buffer.extend(b"Hello, world! This data should remain secure!");
298        let auth_key = get_test_auth_key();
299        let random_padding = [0; 32];
300        let expected = vec![
301            50, 209, 88, 110, 164, 87, 223, 200, 168, 23, 41, 212, 109, 181, 64, 25, 162, 191, 215,
302            247, 68, 249, 185, 108, 79, 113, 108, 253, 196, 71, 125, 178, 162, 193, 95, 109, 219,
303            133, 35, 95, 185, 85, 47, 29, 132, 7, 198, 170, 234, 0, 204, 132, 76, 90, 27, 246, 172,
304            68, 183, 155, 94, 220, 42, 35, 134, 139, 61, 96, 115, 165, 144, 153, 44, 15, 41, 117,
305            36, 61, 86, 62, 161, 128, 210, 24, 238, 117, 124, 154,
306        ];
307
308        do_encrypt_data_v2(&mut buffer, &auth_key, &random_padding);
309        assert_eq!(&buffer[..], expected);
310    }
311
312    #[test]
313    fn decrypt_server_data_v2() {
314        let mut ciphertext = vec![
315            122, 113, 131, 194, 193, 14, 79, 77, 249, 69, 250, 154, 154, 189, 53, 231, 195, 132,
316            11, 97, 240, 69, 48, 79, 57, 103, 76, 25, 192, 226, 9, 120, 79, 80, 246, 34, 106, 7,
317            53, 41, 214, 117, 201, 44, 191, 11, 250, 140, 153, 167, 155, 63, 57, 199, 42, 93, 154,
318            2, 109, 67, 26, 183, 64, 124, 160, 78, 204, 85, 24, 125, 108, 69, 241, 120, 113, 82,
319            78, 221, 144, 206, 160, 46, 215, 40, 225, 77, 124, 177, 138, 234, 42, 99, 97, 88, 240,
320            148, 89, 169, 67, 119, 16, 216, 148, 199, 159, 54, 140, 78, 129, 100, 183, 100, 126,
321            169, 134, 18, 174, 254, 148, 44, 93, 146, 18, 26, 203, 141, 176, 45, 204, 206, 182,
322            109, 15, 135, 32, 172, 18, 160, 109, 176, 88, 43, 253, 149, 91, 227, 79, 54, 81, 24,
323            227, 186, 184, 205, 8, 12, 230, 180, 91, 40, 234, 197, 109, 205, 42, 41, 55, 78,
324        ];
325        let auth_key = AuthKey::from_bytes([
326            93, 46, 125, 101, 244, 158, 194, 139, 208, 41, 168, 135, 97, 234, 39, 184, 164, 199,
327            159, 18, 34, 101, 37, 68, 62, 125, 124, 89, 110, 243, 48, 53, 48, 219, 33, 7, 232, 154,
328            169, 151, 199, 160, 22, 74, 182, 148, 24, 122, 222, 255, 21, 107, 214, 239, 113, 24,
329            161, 150, 35, 71, 117, 60, 14, 126, 137, 160, 53, 75, 142, 195, 100, 249, 153, 126,
330            113, 188, 105, 35, 251, 134, 232, 228, 52, 145, 224, 16, 96, 106, 108, 232, 69, 226,
331            250, 1, 148, 9, 119, 239, 10, 163, 42, 223, 90, 151, 219, 246, 212, 40, 236, 4, 52,
332            215, 23, 162, 211, 173, 25, 98, 44, 192, 88, 135, 100, 33, 19, 199, 150, 95, 251, 134,
333            42, 62, 60, 203, 10, 185, 90, 221, 218, 87, 248, 146, 69, 219, 215, 107, 73, 35, 72,
334            248, 233, 75, 213, 167, 192, 224, 184, 72, 8, 82, 60, 253, 30, 168, 11, 50, 254, 154,
335            209, 152, 188, 46, 16, 63, 206, 183, 213, 36, 146, 236, 192, 39, 58, 40, 103, 75, 201,
336            35, 238, 229, 146, 101, 171, 23, 160, 2, 223, 31, 74, 162, 197, 155, 129, 154, 94, 94,
337            29, 16, 94, 193, 23, 51, 111, 92, 118, 198, 177, 135, 3, 125, 75, 66, 112, 206, 233,
338            204, 33, 7, 29, 151, 233, 188, 162, 32, 198, 215, 176, 27, 153, 140, 242, 229, 205,
339            185, 165, 14, 205, 161, 133, 42, 54, 230, 53, 105, 12, 142,
340        ]);
341        let expected = vec![
342            252, 130, 106, 2, 36, 139, 40, 253, 96, 242, 196, 130, 36, 67, 173, 104, 1, 240, 193,
343            194, 145, 139, 48, 94, 2, 0, 0, 0, 88, 0, 0, 0, 220, 248, 241, 115, 2, 0, 0, 0, 1, 168,
344            193, 194, 145, 139, 48, 94, 1, 0, 0, 0, 28, 0, 0, 0, 8, 9, 194, 158, 196, 253, 51, 173,
345            145, 139, 48, 94, 24, 168, 142, 166, 7, 238, 88, 22, 252, 130, 106, 2, 36, 139, 40,
346            253, 1, 204, 193, 194, 145, 139, 48, 94, 2, 0, 0, 0, 20, 0, 0, 0, 197, 115, 119, 52,
347            196, 253, 51, 173, 145, 139, 48, 94, 100, 8, 48, 0, 0, 0, 0, 0, 252, 230, 103, 4, 163,
348            205, 142, 233, 208, 174, 111, 171, 103, 44, 96, 192, 74, 63, 31, 212, 73, 14, 81, 246,
349        ];
350
351        let plaintext = decrypt_data_v2(&mut ciphertext, &auth_key).unwrap();
352
353        assert_eq!(plaintext, expected);
354    }
355
356    #[test]
357    fn key_from_nonce() {
358        let server_nonce = {
359            let mut buffer = [0u8; 16];
360            buffer
361                .iter_mut()
362                .enumerate()
363                .for_each(|(i, x)| *x = i as u8);
364            buffer
365        };
366        let new_nonce = {
367            let mut buffer = [0u8; 32];
368            buffer
369                .iter_mut()
370                .enumerate()
371                .for_each(|(i, x)| *x = i as u8);
372            buffer
373        };
374
375        let (key, iv) = generate_key_data_from_nonce(&server_nonce, &new_nonce);
376        assert_eq!(
377            key,
378            [
379                7, 88, 241, 83, 59, 97, 93, 36, 246, 232, 169, 74, 111, 203, 238, 10, 85, 234, 171,
380                34, 23, 215, 41, 92, 169, 33, 61, 26, 45, 125, 22, 166
381            ]
382        );
383        assert_eq!(
384            iv,
385            [
386                90, 132, 16, 142, 152, 5, 101, 108, 232, 100, 7, 14, 22, 110, 98, 24, 246, 120, 62,
387                133, 17, 71, 26, 90, 183, 128, 44, 242, 0, 1, 2, 3
388            ]
389        );
390    }
391
392    #[test]
393    fn verify_ige_encryption() {
394        let mut plaintext = get_test_aes_key_or_iv(); // Encrypting the key with itself
395        let key = get_test_aes_key_or_iv();
396        let iv = get_test_aes_key_or_iv();
397        let expected = vec![
398            226, 129, 18, 165, 62, 92, 137, 199, 177, 234, 128, 113, 193, 51, 105, 159, 212, 232,
399            107, 38, 196, 186, 201, 252, 90, 241, 171, 140, 226, 122, 68, 164,
400        ];
401
402        aes::ige_encrypt(&mut plaintext, &key, &iv);
403        let ciphertext = plaintext;
404
405        assert_eq!(ciphertext.as_slice(), &expected);
406    }
407
408    #[test]
409    fn verify_ige_decryption() {
410        let mut ciphertext = get_test_aes_key_or_iv(); // Decrypting the key with itself
411        let key = get_test_aes_key_or_iv();
412        let iv = get_test_aes_key_or_iv();
413        let expected = vec![
414            229, 119, 122, 250, 205, 123, 44, 22, 247, 172, 64, 202, 230, 30, 246, 3, 254, 230, 9,
415            143, 184, 168, 134, 10, 185, 238, 103, 44, 215, 229, 186, 204,
416        ];
417
418        aes::ige_decrypt(&mut ciphertext, &key, &iv);
419        let plaintext = ciphertext;
420
421        assert_eq!(plaintext.as_slice(), &expected);
422    }
423}