ferogram_crypto/
obfuscated.rs1#[allow(deprecated)]
14use aes::cipher::{KeyIvInit, StreamCipher, generic_array::GenericArray};
15
16pub struct ObfuscatedCipher {
18 #[allow(deprecated)]
19 rx: ctr::Ctr128BE<aes::Aes256>,
20 #[allow(deprecated)]
21 tx: ctr::Ctr128BE<aes::Aes256>,
22}
23
24impl ObfuscatedCipher {
25 #[allow(deprecated)]
27 pub fn new(init: &[u8; 64]) -> Self {
28 let rev: Vec<u8> = init.iter().copied().rev().collect();
29 Self {
30 rx: ctr::Ctr128BE::<aes::Aes256>::new(
31 GenericArray::from_slice(&rev[8..40]),
32 GenericArray::from_slice(&rev[40..56]),
33 ),
34 tx: ctr::Ctr128BE::<aes::Aes256>::new(
35 GenericArray::from_slice(&init[8..40]),
36 GenericArray::from_slice(&init[40..56]),
37 ),
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(
52 GenericArray::from_slice(tx_key),
53 GenericArray::from_slice(tx_iv),
54 ),
55 rx: ctr::Ctr128BE::<aes::Aes256>::new(
56 GenericArray::from_slice(rx_key),
57 GenericArray::from_slice(rx_iv),
58 ),
59 }
60 }
61
62 pub fn encrypt(&mut self, buf: &mut [u8]) {
64 self.tx.apply_keystream(buf);
65 }
66
67 pub fn decrypt(&mut self, buf: &mut [u8]) {
69 self.rx.apply_keystream(buf);
70 }
71}
72
73pub fn build_obfuscated_init(
81 framing_byte: u8,
82 dc_id: i16,
83 proxy_secret: Option<&[u8]>,
84) -> ([u8; 64], ObfuscatedCipher) {
85 use sha2::Digest;
86
87 let mut nonce = [0u8; 64];
88 loop {
89 crate::fill_random(&mut nonce);
90 let first = u32::from_le_bytes(nonce[0..4].try_into().expect("4-byte slice"));
91 let second = u32::from_le_bytes(nonce[4..8].try_into().expect("4-byte slice"));
92 let bad = nonce[0] == 0xEF
93 || first == 0x44414548 || first == 0x54534F50 || first == 0x20544547 || first == 0x4954504f || first == 0xEEEEEEEE
98 || first == 0xDDDDDDDD
99 || first == 0x02010316
100 || second == 0x00000000;
101 if !bad {
102 break;
103 }
104 }
105
106 let tx_raw: [u8; 32] = nonce[8..40].try_into().expect("32-byte slice");
107 let tx_iv: [u8; 16] = nonce[40..56].try_into().expect("16-byte slice");
108 let mut rev48 = nonce[8..56].to_vec();
109 rev48.reverse();
110 let rx_raw: [u8; 32] = rev48[0..32].try_into().expect("32-byte slice");
111 let rx_iv: [u8; 16] = rev48[32..48].try_into().expect("16-byte slice");
112
113 let (tx_key, rx_key): ([u8; 32], [u8; 32]) = if let Some(s) = proxy_secret {
114 let mut h = sha2::Sha256::new();
115 h.update(tx_raw);
116 h.update(s);
117 let tx: [u8; 32] = h.finalize().into();
118
119 let mut h = sha2::Sha256::new();
120 h.update(rx_raw);
121 h.update(s);
122 let rx: [u8; 32] = h.finalize().into();
123 (tx, rx)
124 } else {
125 (tx_raw, rx_raw)
126 };
127
128 nonce[56] = framing_byte;
129 nonce[57] = framing_byte;
130 nonce[58] = framing_byte;
131 nonce[59] = framing_byte;
132 let dc_bytes = dc_id.to_le_bytes();
133 nonce[60] = dc_bytes[0];
134 nonce[61] = dc_bytes[1];
135
136 let mut cipher = ObfuscatedCipher::from_keys(&tx_key, &tx_iv, &rx_key, &rx_iv);
137 let mut skip = [0u8; 56];
138 cipher.encrypt(&mut skip);
139 cipher.encrypt(&mut nonce[56..64]);
140
141 (nonce, cipher)
142}
143
144pub fn build_fake_tls_keys(secret: &[u8; 16], tls_record: &[u8]) -> ([u8; 32], ObfuscatedCipher) {
157 use hmac::{Hmac, Mac};
158 use sha2::Digest;
159 type HmacSha256 = Hmac<sha2::Sha256>;
160
161 let mut mac =
163 HmacSha256::new_from_slice(secret).expect("HMAC key error: secret must be non-empty");
164 mac.update(tls_record);
165 let hmac_result: [u8; 32] = mac.finalize().into_bytes().into();
166
167 let mut h = sha2::Sha256::new();
169 h.update(secret.as_ref());
170 h.update(hmac_result);
171 let derived: [u8; 32] = h.finalize().into();
172
173 let iv = [0u8; 16];
174 let cipher = ObfuscatedCipher::from_keys(&derived, &iv, &derived, &iv);
175 (hmac_result, cipher)
176}