Skip to main content

ferogram_crypto/
auth_key.rs

1// Copyright (c) Ankit Chaubey <ankitchaubey.dev@gmail.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3//
4// ferogram: async Telegram MTProto client in Rust
5// https://github.com/ankit-chaubey/ferogram
6//
7// Based on layer: https://github.com/ankit-chaubey/layer
8// Follows official Telegram client behaviour (tdesktop, TDLib).
9//
10// If you use or modify this code, keep this notice at the top of your file
11// and include the LICENSE-MIT or LICENSE-APACHE file from this repository:
12// https://github.com/ankit-chaubey/ferogram
13
14//! Telegram `AuthKey`: 256-byte key derived from the DH handshake.
15
16use crate::sha1;
17
18/// A Telegram authorization key (256 bytes) plus pre-computed identifiers.
19#[derive(Clone)]
20pub struct AuthKey {
21    pub(crate) data: [u8; 256],
22    pub(crate) aux_hash: [u8; 8],
23    pub(crate) key_id: [u8; 8],
24}
25
26impl AuthKey {
27    /// Construct from raw 256-byte DH output.
28    pub fn from_bytes(data: [u8; 256]) -> Self {
29        let sha = sha1!(&data);
30        let mut aux_hash = [0u8; 8];
31        aux_hash.copy_from_slice(&sha[..8]);
32        let mut key_id = [0u8; 8];
33        key_id.copy_from_slice(&sha[12..20]);
34        Self {
35            data,
36            aux_hash,
37            key_id,
38        }
39    }
40
41    /// Return the raw 256-byte representation.
42    pub fn to_bytes(&self) -> [u8; 256] {
43        self.data
44    }
45
46    /// The 8-byte key identifier (SHA-1(key)[12..20]).
47    pub fn key_id(&self) -> [u8; 8] {
48        self.key_id
49    }
50
51    /// Compute the new-nonce hash needed for `DhGenOk/Retry/Fail` verification.
52    pub fn calc_new_nonce_hash(&self, new_nonce: &[u8; 32], number: u8) -> [u8; 16] {
53        let data: Vec<u8> = new_nonce
54            .iter()
55            .copied()
56            .chain([number])
57            .chain(self.aux_hash.iter().copied())
58            .collect();
59        let sha = sha1!(&data);
60        let mut out = [0u8; 16];
61        out.copy_from_slice(&sha[4..]);
62        out
63    }
64}
65
66impl std::fmt::Debug for AuthKey {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        write!(f, "AuthKey(id={})", u64::from_le_bytes(self.key_id))
69    }
70}
71
72impl PartialEq for AuthKey {
73    fn eq(&self, other: &Self) -> bool {
74        self.key_id == other.key_id
75    }
76}