1use crate::{bits_to_rate, keccakf::KeccakF, left_encode, Hasher, KeccakState, Xof};
6
7#[derive(Clone)]
18pub struct CShake {
19 state: KeccakState<KeccakF>,
20}
21
22impl CShake {
23 const DELIM: u8 = 0x04;
24
25 pub fn v128(name: &[u8], custom_string: &[u8]) -> CShake {
29 CShake::new(name, custom_string, 128)
30 }
31
32 pub fn v256(name: &[u8], custom_string: &[u8]) -> CShake {
36 CShake::new(name, custom_string, 256)
37 }
38
39 pub(crate) fn new(name: &[u8], custom_string: &[u8], bits: usize) -> CShake {
40 let rate = bits_to_rate(bits);
41 if name.is_empty() && custom_string.is_empty() {
44 let state = KeccakState::new(rate, 0x1f);
45 return CShake { state };
46 }
47
48 let mut state = KeccakState::new(rate, Self::DELIM);
49 state.update(left_encode(rate).value());
50 state.update(left_encode(name.len() * 8).value());
51 state.update(name);
52 state.update(left_encode(custom_string.len() * 8).value());
53 state.update(custom_string);
54 state.fill_block();
55 CShake { state }
56 }
57
58 pub(crate) fn fill_block(&mut self) {
59 self.state.fill_block();
60 }
61}
62
63impl Hasher for CShake {
64 fn update(&mut self, input: &[u8]) {
65 self.state.update(input);
66 }
67
68 fn finalize(self, output: &mut [u8]) {
69 self.state.finalize(output);
70 }
71}
72
73impl Xof for CShake {
74 fn squeeze(&mut self, output: &mut [u8]) {
75 self.state.squeeze(output);
76 }
77}