use super::HashLen;
use super::Result;
use crypto::digest::Digest;
use crypto::sha3::Sha3;
pub fn hash(input: &[u8], len: HashLen, round: u8) -> Result<Vec<u8>> {
let (mut hasher, size) = match len {
HashLen::Len224 => (Sha3::sha3_224(), 20),
HashLen::Len256 => (Sha3::sha3_256(), 32),
HashLen::Len384 => (Sha3::sha3_384(), 48),
HashLen::Len512 => (Sha3::sha3_512(), 64),
_ => bail!("Sha3 not support hash algo {:?}", len),
};
fn sha3_inner(ret: &mut [u8], hash: &mut Sha3, round: u8) -> Result<Vec<u8>> {
if round <= 0 {
return Ok(ret.to_owned());
}
hash.input(ret);
hash.result(ret);
sha3_inner(ret, hash, round - 1)
}
let mut content = vec![0; size];
hasher.input(input);
hasher.result(&mut content);
sha3_inner(&mut content, &mut hasher, round - 1)
}
#[test]
fn test_sha3() -> Result<()> {
let input = &"hello".as_bytes();
let expect_256_1 = vec![
167, 255, 198, 248, 191, 30, 215, 102, 81, 193, 71, 86, 160, 97, 214, 98, 245, 128, 255,
77, 228, 59, 73, 250, 130, 216, 10, 75, 128, 248, 67, 74,
];
assert_eq!(hash("".as_bytes(), HashLen::Len256, 1)?, expect_256_1);
let expect_256_1 = vec![
51, 56, 190, 105, 79, 80, 197, 243, 56, 129, 73, 134, 205, 240, 104, 100, 83, 168, 136,
184, 79, 66, 77, 121, 42, 244, 185, 32, 35, 152, 243, 146,
];
assert_eq!(hash(input, HashLen::Len256, 1)?, expect_256_1);
let expect_384_1 = vec![
114, 10, 234, 17, 1, 158, 240, 100, 64, 251, 240, 93, 135, 170, 36, 104, 10, 33, 83, 223,
57, 7, 178, 54, 49, 231, 23, 124, 230, 32, 250, 19, 48, 255, 7, 192, 253, 222, 229, 70,
153, 164, 195, 238, 14, 233, 216, 135,
];
assert_eq!(hash(input, HashLen::Len384, 1)?, expect_384_1);
let data = [b'x'; 2_000_000];
let expect_256_1 = vec![
224, 237, 251, 95, 119, 8, 220, 204, 28, 189, 195, 121, 136, 89, 153, 106, 53, 20, 51, 50,
63, 244, 194, 50, 57, 250, 41, 82, 18, 214, 30, 24,
];
assert_eq!(hash(&data, HashLen::Len256, 1)?, expect_256_1);
Ok(())
}