ferogram_crypto/
obfuscated.rs1#[allow(deprecated)]
16use aes::cipher::{Array, KeyIvInit, StreamCipher};
17
18pub struct ObfuscatedCipher {
20 #[allow(deprecated)]
21 rx: ctr::Ctr128BE<aes::Aes256>,
22 #[allow(deprecated)]
23 tx: ctr::Ctr128BE<aes::Aes256>,
24}
25
26impl ObfuscatedCipher {
27 #[allow(deprecated)]
29 pub fn new(init: &[u8; 64]) -> Self {
30 let rev: Vec<u8> = init.iter().copied().rev().collect();
31 let rx_key: [u8; 32] = rev[8..40].try_into().expect("32-byte slice");
32 let rx_iv: [u8; 16] = rev[40..56].try_into().expect("16-byte slice");
33 let tx_key: [u8; 32] = init[8..40].try_into().expect("32-byte slice");
34 let tx_iv: [u8; 16] = init[40..56].try_into().expect("16-byte slice");
35 Self {
36 rx: ctr::Ctr128BE::<aes::Aes256>::new(&Array::from(rx_key), &Array::from(rx_iv)),
37 tx: ctr::Ctr128BE::<aes::Aes256>::new(&Array::from(tx_key), &Array::from(tx_iv)),
38 }
39 }
40
41 #[allow(deprecated)]
44 pub fn from_keys(
45 tx_key: &[u8; 32],
46 tx_iv: &[u8; 16],
47 rx_key: &[u8; 32],
48 rx_iv: &[u8; 16],
49 ) -> Self {
50 Self {
51 tx: ctr::Ctr128BE::<aes::Aes256>::new(&Array::from(*tx_key), &Array::from(*tx_iv)),
52 rx: ctr::Ctr128BE::<aes::Aes256>::new(&Array::from(*rx_key), &Array::from(*rx_iv)),
53 }
54 }
55
56 pub fn encrypt(&mut self, buf: &mut [u8]) {
58 self.tx.apply_keystream(buf);
59 }
60
61 pub fn decrypt(&mut self, buf: &mut [u8]) {
63 self.rx.apply_keystream(buf);
64 }
65}
66
67pub fn build_obfuscated_init(
75 framing_byte: u8,
76 dc_id: i16,
77 proxy_secret: Option<&[u8]>,
78) -> ([u8; 64], ObfuscatedCipher) {
79 use sha2::Digest;
80
81 let mut nonce = [0u8; 64];
82 loop {
83 crate::fill_random(&mut nonce);
84 let first = u32::from_le_bytes(nonce[0..4].try_into().expect("4-byte slice"));
85 let second = u32::from_le_bytes(nonce[4..8].try_into().expect("4-byte slice"));
86 let bad = nonce[0] == 0xEF
87 || first == 0x44414548 || first == 0x54534F50 || first == 0x20544547 || first == 0x4954504f || first == 0xEEEEEEEE
92 || first == 0xDDDDDDDD
93 || first == 0x02010316
94 || second == 0x00000000;
95 if !bad {
96 break;
97 }
98 }
99
100 let tx_raw: [u8; 32] = nonce[8..40].try_into().expect("32-byte slice");
101 let tx_iv: [u8; 16] = nonce[40..56].try_into().expect("16-byte slice");
102 let mut rev48 = nonce[8..56].to_vec();
103 rev48.reverse();
104 let rx_raw: [u8; 32] = rev48[0..32].try_into().expect("32-byte slice");
105 let rx_iv: [u8; 16] = rev48[32..48].try_into().expect("16-byte slice");
106
107 let (tx_key, rx_key): ([u8; 32], [u8; 32]) = if let Some(s) = proxy_secret {
108 let mut h = sha2::Sha256::new();
109 h.update(tx_raw);
110 h.update(s);
111 let tx: [u8; 32] = h.finalize().into();
112
113 let mut h = sha2::Sha256::new();
114 h.update(rx_raw);
115 h.update(s);
116 let rx: [u8; 32] = h.finalize().into();
117 (tx, rx)
118 } else {
119 (tx_raw, rx_raw)
120 };
121
122 nonce[56] = framing_byte;
123 nonce[57] = framing_byte;
124 nonce[58] = framing_byte;
125 nonce[59] = framing_byte;
126 let dc_bytes = dc_id.to_le_bytes();
127 nonce[60] = dc_bytes[0];
128 nonce[61] = dc_bytes[1];
129
130 let mut cipher = ObfuscatedCipher::from_keys(&tx_key, &tx_iv, &rx_key, &rx_iv);
131 let mut skip = [0u8; 56];
132 cipher.encrypt(&mut skip);
133 cipher.encrypt(&mut nonce[56..64]);
134
135 (nonce, cipher)
136}
137
138pub fn fake_tls_client_digest(secret: &[u8; 16], record: &[u8]) -> [u8; 32] {
148 use hmac::{Hmac, KeyInit, Mac};
149 type HmacSha256 = Hmac<sha2::Sha256>;
150
151 let mut mac =
152 HmacSha256::new_from_slice(secret).expect("HMAC key error: secret must be non-empty");
153 mac.update(record);
154 let mut digest: [u8; 32] = mac.finalize().into_bytes().into();
155
156 let now = std::time::SystemTime::now()
157 .duration_since(std::time::UNIX_EPOCH)
158 .map(|d| d.as_secs() as u32)
159 .unwrap_or(0);
160 let last4 = u32::from_le_bytes(digest[28..32].try_into().expect("4-byte slice")) ^ now;
161 digest[28..32].copy_from_slice(&last4.to_le_bytes());
162 digest
163}
164
165pub fn fake_tls_verify_server_digest(
175 secret: &[u8; 16],
176 client_digest: &[u8; 32],
177 packet_with_digest_zeroed: &[u8],
178 expected_digest: &[u8; 32],
179) -> bool {
180 use hmac::{Hmac, KeyInit, Mac};
181 type HmacSha256 = Hmac<sha2::Sha256>;
182
183 let mut mac =
184 HmacSha256::new_from_slice(secret).expect("HMAC key error: secret must be non-empty");
185 mac.update(client_digest);
186 mac.update(packet_with_digest_zeroed);
187 let computed: [u8; 32] = mac.finalize().into_bytes().into();
188 computed == *expected_digest
189}