use super::hash_ctx::HashCtx;
use crate::algorithm::hash;
use crate::algorithm::hash::HashType;
use crate::constant;
pub struct Hash {
pub iv_c_s: Vec<u8>,
pub iv_s_c: Vec<u8>,
pub ek_c_s: Vec<u8>,
pub ek_s_c: Vec<u8>,
pub ik_c_s: Vec<u8>,
pub ik_s_c: Vec<u8>,
hash_type: HashType,
hash_ctx: HashCtx,
}
impl Hash {
pub fn new(hash_ctx: HashCtx, session_id: &[u8], hash_type: HashType) -> Self {
let k = hash_ctx.k.as_slice();
let h = hash::digest(&hash_ctx.as_bytes(), hash_type);
let mut keys = vec![];
for v in constant::ALPHABET {
keys.push(Hash::mix(k, &h, v, session_id, hash_type));
}
Hash {
iv_c_s: keys[0].clone(),
iv_s_c: keys[1].clone(),
ek_c_s: keys[2].clone(),
ek_s_c: keys[3].clone(),
ik_c_s: keys[4].clone(),
ik_s_c: keys[5].clone(),
hash_type,
hash_ctx,
}
}
fn mix(k: &[u8], h: &[u8], key_char: u8, session_id: &[u8], hash_type: HashType) -> Vec<u8> {
let mut key: Vec<u8> = Vec::new();
key.extend(k);
key.extend(h);
key.push(key_char);
key.extend(session_id);
hash::digest(key.as_slice(), hash_type)
}
pub fn mix_ek(&self, key_size: usize) -> (Vec<u8>, Vec<u8>) {
let mut ck = self.ek_c_s.to_vec();
let mut sk = self.ek_s_c.to_vec();
while key_size > ck.len() {
ck.extend(self.extend(ck.as_slice()));
sk.extend(self.extend(sk.as_slice()));
}
(ck, sk)
}
pub fn mix_ik(&self, key_size: usize) -> (Vec<u8>, Vec<u8>) {
let mut ck = self.ik_c_s.to_vec();
let mut sk = self.ik_s_c.to_vec();
while key_size > ck.len() {
ck.extend(self.extend(ck.as_slice()));
sk.extend(self.extend(sk.as_slice()));
}
(ck, sk)
}
fn extend(&self, key: &[u8]) -> Vec<u8> {
let k = self.hash_ctx.k.clone();
let h = hash::digest(self.hash_ctx.as_bytes().as_slice(), self.hash_type);
let mut hash: Vec<u8> = Vec::new();
hash.extend(k);
hash.extend(h);
hash.extend(key);
hash::digest(hash.as_slice(), self.hash_type)
}
}