use super::HashLen;
use super::Result;
use tiny_keccak::Keccak;
pub fn hash(input: &[u8], len: HashLen, round: u8) -> Result<Vec<u8>> {
let (mut hasher, size) = match len {
HashLen::Len224 => (Keccak::new_keccak224(), 20),
HashLen::Len256 => (Keccak::new_keccak256(), 32),
HashLen::Len384 => (Keccak::new_keccak384(), 48),
HashLen::Len512 => (Keccak::new_keccak512(), 64),
_ => bail!("keccak_f1600 not support hash algo {:?}", len),
};
fn skeccak_f1600_inner(ret: &mut [u8], hash: &mut Keccak, round: u8) -> Result<Vec<u8>> {
if round <= 0 {
return Ok(ret.to_owned());
}
(*hash).update(ret);
(*hash).clone().finalize(ret);
skeccak_f1600_inner(ret, hash, round - 1)
}
let mut content = vec![0; size];
hasher.update(input);
hasher.clone().finalize(&mut content);
skeccak_f1600_inner(&mut content, &mut hasher, round - 1)
}
#[test]
fn test_keccak_f1600() -> Result<()> {
let input = &"hello".as_bytes();
let expect_256_1 = vec![
197, 210, 70, 1, 134, 247, 35, 60, 146, 126, 125, 178, 220, 199, 3, 192, 229, 0, 182, 83,
202, 130, 39, 59, 123, 250, 216, 4, 93, 133, 164, 112,
];
assert_eq!(hash("".as_bytes(), HashLen::Len256, 1)?, expect_256_1);
let expect_256_1 = vec![
28, 138, 255, 149, 6, 133, 194, 237, 75, 195, 23, 79, 52, 114, 40, 123, 86, 217, 81, 123,
156, 148, 129, 39, 49, 154, 9, 167, 163, 109, 234, 200,
];
assert_eq!(hash(input, HashLen::Len256, 1)?, expect_256_1);
let expect_384_1 = vec![
220, 239, 111, 183, 144, 143, 213, 43, 162, 106, 171, 167, 81, 33, 82, 106, 187, 241, 33,
127, 28, 10, 49, 2, 70, 82, 209, 52, 211, 227, 47, 180, 205, 142, 156, 112, 59, 143, 67,
231, 39, 123, 89, 165, 205, 64, 33, 117,
];
assert_eq!(hash(input, HashLen::Len384, 1)?, expect_384_1);
Ok(())
}