glow_control_lib/util/
auth.rs1use crate::util::rc4::Rc4;
2use anyhow::Result;
3use rand::RngCore;
4use sha1::Digest;
5use sha1::Sha1;
6
7const SHARED_KEY_CHALLENGE: &[u8] = b"evenmoresecret!!";
8pub struct Auth;
9
10impl Auth {
11 pub fn make_challenge_response(challenge: &[u8], mac_address: &str) -> Result<String> {
12 let derived_key = Self::derive_key(SHARED_KEY_CHALLENGE, mac_address);
13 let mut rc4_cipher = Rc4::new(&derived_key);
14 let mut encrypted_challenge = challenge.to_vec();
15 rc4_cipher.apply_keystream(&mut encrypted_challenge);
16
17 let mut hasher = Sha1::new();
18 hasher.update(&encrypted_challenge);
19 let result = hasher.finalize();
20
21 Ok(hex::encode(result))
22 }
23
24 pub fn mac_to_bytes(mac: &str) -> Vec<u8> {
26 mac.split(':')
27 .map(|part| u8::from_str_radix(part, 16).unwrap())
28 .collect()
29 }
30
31 pub fn derive_key(shared_key: &[u8], mac_address: &str) -> Vec<u8> {
33 let mac_bytes = Self::mac_to_bytes(mac_address);
34 let mut derived_key = Vec::new();
35 for (i, &byte) in shared_key.iter().enumerate() {
36 derived_key.push(byte ^ mac_bytes[i % mac_bytes.len()]);
37 }
38 derived_key
39 }
40
41 pub fn generate_challenge() -> Vec<u8> {
42 let mut challenge = vec![0u8; 32];
43 rand::thread_rng().fill_bytes(&mut challenge);
44 challenge
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn test_generate_challenge() {
54 let challenge = Auth::generate_challenge();
55 assert_eq!(challenge.len(), 32);
56 }
57}