Skip to main content

ferogram_crypto/
auth_key.rs

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