1use super::keccak::Keccak;
2use crate::Xof;
3
4pub(crate) const SHAKE128_RATE: usize = 168;
5const SHAKE128_DOMAIN_SEPARATOR: u8 = 0x1f;
6
7#[derive(Clone)]
32pub struct Shake128 {
33 keccak: Keccak<24>,
34}
35
36impl Shake128 {
37 #[inline]
38 pub fn new() -> Self {
39 return Shake128 {
40 keccak: Keccak::new(SHAKE128_RATE, SHAKE128_DOMAIN_SEPARATOR),
41 };
42 }
43
44 #[inline]
45 pub fn hash(data: &[u8], output: &mut [u8]) {
46 let mut hasher = Shake128::new();
47 hasher.absorb(data);
48 hasher.squeeze(output);
49 }
50}
51
52impl Xof for Shake128 {
53 #[inline]
54 fn absorb(&mut self, data: &[u8]) {
55 self.keccak.absorb(data);
56 }
57
58 #[inline]
59 fn squeeze(&mut self, out: &mut [u8]) {
60 self.keccak.squeeze(out);
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::Shake128;
67 use crate::Xof;
68
69 fn vectors_shake128() -> Vec<(Vec<u8>, usize, &'static str)> {
71 vec![
72 (
73 b"".to_vec(),
74 32,
75 "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26",
76 ),
77 (
78 b"".to_vec(),
79 64,
80 "7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef263cb1eea988004b93103cfb0aeefd2a686e01fa4a58e8a3639ca8a1e3f9ae57e2",
81 ),
82 (
83 b"abc".to_vec(),
84 32,
85 "5881092dd818bf5cf8a3ddb793fbcba74097d5c526a6d35f97b83351940f2cc8",
86 ),
87 (
88 b"The quick brown fox jumps over the lazy dog".to_vec(),
89 32,
90 "f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e",
91 ),
92 ]
93 }
94
95 #[test]
96 fn known_vectors() {
97 for (input, output_len, expected) in vectors_shake128() {
98 let mut output = vec![0u8; output_len];
99 Shake128::hash(&input, &mut output);
100 assert_eq!(hex::encode(&output), expected);
101 }
102 }
103
104 #[test]
105 fn incremental_and_streaming_read() {
106 let mut one_shot = vec![0u8; 64];
107 Shake128::hash(b"", &mut one_shot);
108
109 let mut shake = Shake128::new();
110 shake.absorb(b"");
111 let mut first = [0u8; 32];
112 let mut second = [0u8; 32];
113 shake.squeeze(&mut first);
114 shake.squeeze(&mut second);
115
116 let mut combined = vec![0u8; 64];
117 combined[..32].copy_from_slice(&first);
118 combined[32..].copy_from_slice(&second);
119
120 assert_eq!(combined, one_shot);
121 }
122}