pub struct HashResult { result: [u64; 4], } impl HashResult { pub fn hex(&self) { for i in 0..4 { print!("{:016X}", self.result[i]); } println!(); } } pub fn ascon256(input: &[u8]) -> HashResult { let mut state = [0u64; 5]; state[0] = 0x00400c0000000100; state = permutate(state); let mut chunked_iterator = input.chunks_exact(8); let mut sized_chunk = [0u8; 8]; for chunk in &mut chunked_iterator { sized_chunk.copy_from_slice(chunk); state[0] ^= u64::from_be_bytes(sized_chunk); state = permutate(state); } let remainder = chunked_iterator.remainder(); if !remainder.is_empty() { sized_chunk = [0u8; 8]; sized_chunk[..remainder.len()].copy_from_slice(remainder); sized_chunk[remainder.len()] |= 0x80; state[0] ^= u64::from_be_bytes(sized_chunk); } let mut res = HashResult { result: [0u64; 4] }; state = permutate(state); for i in 0..3 { res.result[i] = state[0]; state = permutate(state); } res.result[3] = state[0]; res } fn permutate(input: [u64; 5]) -> [u64; 5] { let mut state = input; for i in 0..12 { state = diffusion(sbox(add_constants(i, state))); } state } fn diffusion(input: [u64; 5]) -> [u64; 5] { let [mut x0, mut x1, mut x2, mut x3, mut x4] = input; x0 ^= x0.rotate_right(19) ^ x0.rotate_right(28); x1 ^= x1.rotate_right(61) ^ x1.rotate_right(39); x2 ^= x2.rotate_right(1) ^ x2.rotate_right(6); x3 ^= x3.rotate_right(10) ^ x3.rotate_right(17); x4 ^= x4.rotate_right(7) ^ x4.rotate_right(41); [x0, x1, x2, x3, x4] } fn add_constants(round: u64, mut input: [u64; 5]) -> [u64; 5] { input[2] ^= ((0b1111 - round) << 4) | round; input } fn sbox(input: [u64; 5]) -> [u64; 5] { let [mut x0, mut x1, mut x2, mut x3, mut x4] = input; x0 ^= x4; x4 ^= x3; x2 ^= x1; let mut t0 = !x0; let mut t1 = !x1; let mut t2 = !x2; let mut t3 = !x3; let mut t4 = !x4; t0 &= x1; t1 &= x2; t2 &= x3; t3 &= x4; t4 &= x0; x0 ^= t1; x1 ^= t2; x2 ^= t3; x3 ^= t4; x4 ^= t0; x1 ^= x0; x0 ^= x4; x3 ^= x2; [x0, x1, !x2, x3, x4] }