use crate::crypto_systems::mix::{Mix, MixKey};
use crate::error::MixError;
use crate::prelude::ALPHABET_LEN;
use crate::utils::decode_list;
use crate::Traits::Encrypt;
use nalgebra::DMatrix;
pub fn mix_function(r: Vec<usize>, k: Vec<usize>) -> Vec<usize> {
let p = DMatrix::from_row_slice(
4,
4,
&[
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0,
],
);
let result = (p * DMatrix::from_row_slice(4, 1, &r).map(|x| x as f64)
+ DMatrix::from_row_slice(4, 1, &k).map(|x| x as f64))
.map(|x| (x) as usize % *ALPHABET_LEN);
result.iter().copied().collect::<Vec<usize>>()
}
impl Encrypt<MixError, String, String> for Mix {
fn encrypt(&self, input: String) -> Result<String, MixError> {
let parsed_input = match self.get_split_input(input) {
Ok(input) => input,
Err(e) => return Err(e),
};
let mut l = parsed_input[0].clone();
let mut r = parsed_input[1].clone();
for i in 0..self.rounds {
let k = self.key.keys[i].clone();
let new_r = mix_function(r.clone(), k);
let updated_new_r = new_r
.iter()
.zip(l.iter())
.map(|(&x, &y)| (x + y) % *ALPHABET_LEN)
.collect::<Vec<usize>>();
let new_l = r;
r = updated_new_r;
l = new_l;
}
let combined = l.iter().chain(r.iter()).copied().collect::<Vec<usize>>();
Ok(decode_list(combined).unwrap())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::utils::decode_list;
#[test]
fn test_mix_function() {
let r = vec![25, 13, 0, 3];
let l = [17, 27, 19, 12];
let k = vec![0, 27, 27, 0];
let result = mix_function(r, k);
let expected = vec![25, 15, 24, 0];
assert_eq!(result, expected);
let new_r = result
.iter()
.zip(l.iter())
.map(|(&x, &y)| (x + y) % *ALPHABET_LEN)
.collect::<Vec<usize>>();
assert_eq!(new_r, vec![14, 14, 15, 12]);
}
#[test]
fn test_encrypt() {
let k1 = vec![0, 27, 27, 0];
let k2 = vec![1, 0, 0, 1];
let k3 = vec![15, 15, 15, 15];
let clear_text = "rötmånad".to_string();
let key = MixKey::new(k1, k2, k3).expect("Key is invalid");
let mix = Mix::new(key);
let result = mix.encrypt(clear_text);
let expected =
decode_list(vec![12, 11, 1, 17, 13, 1, 15, 1]).expect("Error in parsing vec");
assert_eq!(result.unwrap(), expected);
}
}