use crate::crypto::hmac::Hmac;
use siphasher::sip::SipHasher24;
use zeroize::Zeroize;
use alloc::vec::Vec;
struct KeyContext {
sip_key1: u64,
sip_key2: u64,
sip_iv: Vec<u8>,
}
pub struct SipHash {
sender: KeyContext,
receiver: KeyContext,
}
impl SipHash {
fn derive_keys(key: &[u8], h: &[u8]) -> (KeyContext, KeyContext) {
let mut temp_key = {
let mut ask_master = Hmac::new(key).update(&b"ask"[..]).update([0x01]).finalize();
let temp_key = Hmac::new(&ask_master).update(h).update(&b"siphash"[..]).finalize();
let mut sip_master = Hmac::new(&temp_key).update([0x01]).finalize();
let temp_key = Hmac::new(&sip_master).update([]).finalize();
ask_master.zeroize();
sip_master.zeroize();
temp_key
};
let sipkeys_ab = Hmac::new(&temp_key).update([0x01]).finalize();
let sipkeys_ba = Hmac::new(&temp_key).update(&sipkeys_ab).update([0x02]).finalize();
temp_key.zeroize();
let (sipk1_initiator, sipk2_initiator, sipiv_initiator) = {
(
u64::from_le_bytes(
TryInto::<[u8; 8]>::try_into(&sipkeys_ab[..8]).expect("to succeed"),
),
u64::from_le_bytes(
TryInto::<[u8; 8]>::try_into(&sipkeys_ab[8..16]).expect("to succeed"),
),
sipkeys_ab[16..24].to_vec(),
)
};
let (sipk1_responder, sipk2_responder, sipiv_responder) = {
(
u64::from_le_bytes(
TryInto::<[u8; 8]>::try_into(&sipkeys_ba[..8]).expect("to succeed"),
),
u64::from_le_bytes(
TryInto::<[u8; 8]>::try_into(&sipkeys_ba[8..16]).expect("to succeed"),
),
sipkeys_ba[16..24].to_vec(),
)
};
(
KeyContext {
sip_key1: sipk1_initiator,
sip_key2: sipk2_initiator,
sip_iv: sipiv_initiator,
},
KeyContext {
sip_key1: sipk1_responder,
sip_key2: sipk2_responder,
sip_iv: sipiv_responder,
},
)
}
pub fn new_initiator(key: &[u8], h: &[u8]) -> Self {
let (initiator, responder) = Self::derive_keys(key, h);
Self {
sender: initiator,
receiver: responder,
}
}
pub fn new_responder(key: &[u8], h: &[u8]) -> Self {
let (initiator, responder) = Self::derive_keys(key, h);
Self {
sender: responder,
receiver: initiator,
}
}
pub fn deobfuscate(&mut self, size: u16) -> u16 {
let hasher = SipHasher24::new_with_keys(self.receiver.sip_key1, self.receiver.sip_key2);
let hash: u64 = hasher.hash(&self.receiver.sip_iv);
self.receiver.sip_iv = hash.to_le_bytes().to_vec();
size ^ ((hash & 0xffff) as u16)
}
pub fn obfuscate(&mut self, size: u16) -> u16 {
let hasher = SipHasher24::new_with_keys(self.sender.sip_key1, self.sender.sip_key2);
let hash: u64 = hasher.hash(&self.sender.sip_iv);
self.sender.sip_iv = hash.to_le_bytes().to_vec();
size ^ ((hash & 0xffff) as u16)
}
}