1use super::keccak::Keccak;
2use crate::{Hash, Hasher, Xof, bytes::Bytes};
3
4pub(crate) const SHAKE256_RATE: usize = 136;
5const CSHAKE256_DOMAIN_SEPARATOR: u8 = 0x04;
6const SHAKE256_DOMAIN_SEPARATOR: u8 = 0x1f;
7
8type EncodedBytes = Bytes<9>;
10
11#[derive(Clone)]
12#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
13pub struct Shake256 {
14 keccak: Keccak<24>,
15}
16
17impl Shake256 {
18 #[inline]
19 pub fn hash(data: &[u8], output: &mut [u8]) {
20 let mut hasher = Shake256::new();
21 hasher.absorb(data);
22 hasher.squeeze(output);
23 }
24
25 #[inline]
26 pub fn new() -> Self {
27 return Shake256 {
28 keccak: Keccak::new(SHAKE256_RATE, SHAKE256_DOMAIN_SEPARATOR),
29 };
30 }
31}
32
33impl Xof for Shake256 {
34 #[inline]
35 fn absorb(&mut self, data: &[u8]) {
36 self.keccak.absorb(data);
37 }
38
39 #[inline]
40 fn squeeze(&mut self, out: &mut [u8]) {
41 self.keccak.squeeze(out);
42 }
43}
44
45impl Hasher for Shake256 {
46 const BLOCK_SIZE: usize = SHAKE256_RATE;
47 const OUTPUT_SIZE: usize = 64;
48
49 #[inline]
50 fn new() -> Self {
51 return Shake256::new();
52 }
53
54 #[inline]
55 fn update(&mut self, data: &[u8]) {
56 self.absorb(data);
57 }
58
59 #[inline]
60 fn sum(mut self) -> Hash {
61 let mut hash = Hash::with_length(Self::OUTPUT_SIZE);
62 self.squeeze(hash.as_mut());
63 return hash;
64 }
65}
66
67#[derive(Clone)]
68#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
69pub struct CShake256 {
70 keccak: Keccak<24>,
71}
72
73impl CShake256 {
74 #[inline]
75 pub fn hash(data: &[u8], function_name: &[u8], customization: &[u8], output: &mut [u8]) {
76 let mut xof = CShake256::new(function_name, customization);
77 xof.absorb(data);
78 xof.squeeze(output);
79 }
80
81 #[inline]
82 pub fn new(function_name: &[u8], customization: &[u8]) -> Self {
83 if function_name.is_empty() && customization.is_empty() {
84 return CShake256 {
85 keccak: Keccak::new(SHAKE256_RATE, SHAKE256_DOMAIN_SEPARATOR),
86 };
87 }
88
89 let mut keccak = Keccak::new(SHAKE256_RATE, CSHAKE256_DOMAIN_SEPARATOR);
90
91 let enc_w = left_encode(SHAKE256_RATE);
95 keccak.absorb(enc_w.as_ref());
96
97 let enc_n = left_encode(function_name.len() * 8);
99 keccak.absorb(enc_n.as_ref());
100 keccak.absorb(function_name);
101
102 let enc_s = left_encode(customization.len() * 8);
104 keccak.absorb(enc_s.as_ref());
105 keccak.absorb(customization);
106
107 let total = enc_w.len() + enc_n.len() + function_name.len() + enc_s.len() + customization.len();
109 let pad = (SHAKE256_RATE - (total % SHAKE256_RATE)) % SHAKE256_RATE;
110 if pad > 0 {
111 let zeros = [0u8; SHAKE256_RATE];
112 keccak.absorb(&zeros[..pad]);
113 }
114
115 return CShake256 {
116 keccak,
117 };
118 }
119}
120
121impl Xof for CShake256 {
122 #[inline]
123 fn absorb(&mut self, data: &[u8]) {
124 self.keccak.absorb(data);
125 }
126
127 #[inline]
128 fn squeeze(&mut self, out: &mut [u8]) {
129 self.keccak.squeeze(out);
130 }
131}
132
133#[inline]
136pub(crate) fn left_encode(x: usize) -> EncodedBytes {
137 let bytes = x.to_be_bytes();
138 let first_non_zero = bytes.iter().position(|&b| b != 0).unwrap_or(bytes.len() - 1);
139 let n = bytes.len() - first_non_zero;
140
141 let mut out = Bytes::new();
142 out.push(n as u8);
143 out.append(&bytes[first_non_zero..]);
144 return out;
145}
146
147#[inline]
148pub(crate) fn right_encode(x: usize) -> EncodedBytes {
149 let mut bytes = left_encode(x);
150 let out = bytes.as_mut();
151 let n = out[0];
152 out[0] = out[1];
153 for i in 1..(n as usize) {
154 out[i] = out[i + 1];
155 }
156 out[n as usize] = n;
157 return bytes;
158}
159
160#[cfg(test)]
184mod tests {
185 use super::{CShake256, Shake256};
186 use crate::{Hasher, Xof};
187
188 fn vectors_shake256() -> Vec<(Vec<u8>, usize, &'static str)> {
191 vec![
192 (
193 b"".to_vec(),
194 64,
195 "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be",
196 ),
197 (
198 b"".to_vec(),
199 128,
200 "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be141e96616fb13957692cc7edd0b45ae3dc07223c8e92937bef84bc0eab862853349ec75546f58fb7c2775c38462c5010d846c185c15111e595522a6bcd16cf86",
201 ),
202 (
203 b"abc".to_vec(),
204 64,
205 "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4",
206 ),
207 (
208 b"hello world".to_vec(),
209 64,
210 "369771bb2cb9d2b04c1d54cca487e372d9f187f73f7ba3f65b95c8ee7798c527f4f3c2d55c2d46a29f2e945d469c3df27853a8735271f5cc2d9e889544357116",
211 ),
212 (
213 b"The quick brown fox jumps over the lazy dog".to_vec(),
214 64,
215 "2f671343d9b2e1604dc9dcf0753e5fe15c7c64a0d283cbbf722d411a0e36f6ca1d01d1369a23539cd80f7c054b6e5daf9c962cad5b8ed5bd11998b40d5734442",
216 ),
217 (
218 b"The quick brown fox jumps over the lazy dog.".to_vec(),
219 64,
220 "bd225bfc8b255f3036f0c8866010ed0053b5163a3cae111e723c0c8e704eca4e5d0f1e2a2fa18c8a219de6b88d5917ff5dd75b5fb345e7409a3b333b508a65fb",
221 ),
222 (
223 vec![b'a'; 1_000_000],
224 64,
225 "3578a7a4ca9137569cdf76ed617d31bb994fca9c1bbf8b184013de8234dfd13a3fd124d4df76c0a539ee7dd2f6e1ec346124c815d9410e145eb561bcd97b18ab",
226 ),
227 ]
228 }
229
230 #[test]
231 fn known_vectors() {
232 for (input, output_len, expected) in vectors_shake256() {
233 let mut output = vec![0u8; output_len];
234 Shake256::hash(&input, &mut output);
235 assert_eq!(hex::encode(output), expected);
236 }
237 }
238
239 #[test]
240 fn incremental_and_streaming_read() {
241 let mut one_shot = vec![0u8; 128];
242 Shake256::hash(b"", &mut one_shot);
243
244 let mut shake = Shake256::new();
245 shake.absorb(b"");
246 let mut first = [0u8; 64];
247 let mut second = [0u8; 64];
248 shake.squeeze(&mut first);
249 shake.squeeze(&mut second);
250
251 let mut combined = vec![0u8; 128];
252 combined[..64].copy_from_slice(&first);
253 combined[64..].copy_from_slice(&second);
254
255 assert_eq!(combined, one_shot);
256 }
257
258 #[test]
259 fn hasher_trait_impl() {
260 let expected = "369771bb2cb9d2b04c1d54cca487e372d9f187f73f7ba3f65b95c8ee7798c527f4f3c2d55c2d46a29f2e945d469c3df27853a8735271f5cc2d9e889544357116";
261 let digest = <Shake256 as Hasher>::hash(b"hello world");
262 assert_eq!(hex::encode(digest.as_ref()), expected);
263 }
264
265 #[test]
266 fn xof_trait_impl() {
267 let mut xof = Shake256::new();
268 xof.absorb(b"abc");
269 let mut out = [0u8; 64];
270 xof.squeeze(&mut out);
271 assert_eq!(
272 hex::encode(out),
273 "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4"
274 );
275 }
276
277 const EMAIL_SIGNATURE: &[u8] = b"Email Signature";
280 const SAMPLE_3_EXPECTED: &str = "d008828e2b80ac9d2218ffee1d070c48b8e4c87bff32c9699d5b6896eee0edd164020e2be0560858d9c00c037e34a96937c561a74c412bb4c746469527281c8c";
281 const SAMPLE_4_EXPECTED: &str = "07dc27b11e51fbac75bc7b3c1d983e8b4b85fb1defaf218912ac86430273091727f42b17ed1df63e8ec118f04b23633c1dfb1574c8fb55cb45da8e25afb092bb";
282
283 #[test]
284 fn cshake256_nist_sample_3() {
285 let mut out = [0u8; 64];
286 CShake256::hash(&[0x00, 0x01, 0x02, 0x03], b"", EMAIL_SIGNATURE, &mut out);
287 assert_eq!(hex::encode(out), SAMPLE_3_EXPECTED);
288 }
289
290 #[test]
291 fn cshake256_nist_sample_4() {
292 let input: Vec<u8> = (0u8..200).collect();
293 let mut out = [0u8; 64];
294 CShake256::hash(&input, b"", EMAIL_SIGNATURE, &mut out);
295 assert_eq!(hex::encode(out), SAMPLE_4_EXPECTED);
296 }
297
298 #[test]
299 fn cshake256_incremental_matches_one_shot() {
300 let input: Vec<u8> = (0u8..200).collect();
301 let mut one_shot = [0u8; 64];
302 CShake256::hash(&input, b"", EMAIL_SIGNATURE, &mut one_shot);
303
304 let mut cshake = CShake256::new(b"", EMAIL_SIGNATURE);
305 for chunk in input.chunks(9) {
306 cshake.absorb(chunk);
307 }
308 let mut streamed = [0u8; 64];
309 cshake.squeeze(&mut streamed);
310 assert_eq!(streamed, one_shot);
311 }
312
313 #[test]
314 fn cshake256_empty_params_passes_shake256_vectors() {
315 for (input, output_len, expected) in vectors_shake256() {
316 let mut cshake_out = vec![0u8; output_len];
317 CShake256::hash(&input, b"", b"", &mut cshake_out);
318 assert_eq!(hex::encode(cshake_out), expected);
319 }
320 }
321
322 #[test]
323 fn cshake256_xof_trait_impl() {
324 let mut xof = CShake256::new(b"", b"");
325 xof.absorb(b"abc");
326 let mut out = [0u8; 64];
327 xof.squeeze(&mut out);
328 assert_eq!(
329 hex::encode(out),
330 "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4"
331 );
332 }
333}