Skip to main content

layer_crypto/
auth_key.rs

1//! Telegram `AuthKey`: 256-byte key derived from the DH handshake.
2
3use crate::sha1;
4
5/// A Telegram authorization key (256 bytes) plus pre-computed identifiers.
6#[derive(Clone)]
7pub struct AuthKey {
8    pub(crate) data: [u8; 256],
9    pub(crate) aux_hash: [u8; 8],
10    pub(crate) key_id: [u8; 8],
11}
12
13impl AuthKey {
14    /// Construct from raw 256-byte DH output.
15    pub fn from_bytes(data: [u8; 256]) -> Self {
16        let sha = sha1!(&data);
17        let mut aux_hash = [0u8; 8];
18        aux_hash.copy_from_slice(&sha[..8]);
19        let mut key_id = [0u8; 8];
20        key_id.copy_from_slice(&sha[12..20]);
21        Self {
22            data,
23            aux_hash,
24            key_id,
25        }
26    }
27
28    /// Return the raw 256-byte representation.
29    pub fn to_bytes(&self) -> [u8; 256] {
30        self.data
31    }
32
33    /// The 8-byte key identifier (SHA-1(key)[12..20]).
34    pub fn key_id(&self) -> [u8; 8] {
35        self.key_id
36    }
37
38    /// Compute the new-nonce hash needed for `DhGenOk/Retry/Fail` verification.
39    pub fn calc_new_nonce_hash(&self, new_nonce: &[u8; 32], number: u8) -> [u8; 16] {
40        let data: Vec<u8> = new_nonce
41            .iter()
42            .copied()
43            .chain([number])
44            .chain(self.aux_hash.iter().copied())
45            .collect();
46        let sha = sha1!(&data);
47        let mut out = [0u8; 16];
48        out.copy_from_slice(&sha[4..]);
49        out
50    }
51}
52
53impl std::fmt::Debug for AuthKey {
54    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55        write!(f, "AuthKey(id={})", u64::from_le_bytes(self.key_id))
56    }
57}
58
59impl PartialEq for AuthKey {
60    fn eq(&self, other: &Self) -> bool {
61        self.key_id == other.key_id
62    }
63}