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)]
36#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
37pub struct Shake256 {
38 keccak: Keccak<24>,
39}
40
41impl Shake256 {
42 #[inline]
43 pub fn hash(data: &[u8], output: &mut [u8]) {
44 let mut hasher = Shake256::new();
45 hasher.absorb(data);
46 hasher.squeeze(output);
47 }
48
49 #[inline]
50 pub fn new() -> Self {
51 return Shake256 {
52 keccak: Keccak::new(SHAKE256_RATE, SHAKE256_DOMAIN_SEPARATOR),
53 };
54 }
55}
56
57impl Xof for Shake256 {
58 #[inline]
59 fn absorb(&mut self, data: &[u8]) {
60 self.keccak.absorb(data);
61 }
62
63 #[inline]
64 fn squeeze(&mut self, out: &mut [u8]) {
65 self.keccak.squeeze(out);
66 }
67}
68
69impl Hasher for Shake256 {
70 const BLOCK_SIZE: usize = SHAKE256_RATE;
71 const OUTPUT_SIZE: usize = 64;
72
73 #[inline]
74 fn new() -> Self {
75 return Shake256::new();
76 }
77
78 #[inline]
79 fn update(&mut self, data: &[u8]) {
80 self.absorb(data);
81 }
82
83 #[inline]
84 fn sum(mut self) -> Hash {
85 let mut hash = Bytes::<64>::with_length(Self::OUTPUT_SIZE);
86 self.squeeze(hash.as_mut());
87 return Hash(hash);
88 }
89}
90
91#[derive(Clone)]
119#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
120pub struct CShake256 {
121 keccak: Keccak<24>,
122}
123
124impl CShake256 {
125 #[inline]
126 pub fn hash(data: &[u8], function_name: &[u8], customization: &[u8], output: &mut [u8]) {
127 let mut xof = CShake256::new(function_name, customization);
128 xof.absorb(data);
129 xof.squeeze(output);
130 }
131
132 #[inline]
133 pub fn new(function_name: &[u8], customization: &[u8]) -> Self {
134 if function_name.is_empty() && customization.is_empty() {
135 return CShake256 {
136 keccak: Keccak::new(SHAKE256_RATE, SHAKE256_DOMAIN_SEPARATOR),
137 };
138 }
139
140 let mut keccak = Keccak::new(SHAKE256_RATE, CSHAKE256_DOMAIN_SEPARATOR);
141
142 let enc_w = left_encode(SHAKE256_RATE);
146 keccak.absorb(enc_w.as_ref());
147
148 let enc_n = left_encode(function_name.len() * 8);
150 keccak.absorb(enc_n.as_ref());
151 keccak.absorb(function_name);
152
153 let enc_s = left_encode(customization.len() * 8);
155 keccak.absorb(enc_s.as_ref());
156 keccak.absorb(customization);
157
158 let total = enc_w.len() + enc_n.len() + function_name.len() + enc_s.len() + customization.len();
160 let pad = (SHAKE256_RATE - (total % SHAKE256_RATE)) % SHAKE256_RATE;
161 if pad > 0 {
162 let zeros = [0u8; SHAKE256_RATE];
163 keccak.absorb(&zeros[..pad]);
164 }
165
166 return CShake256 {
167 keccak,
168 };
169 }
170}
171
172impl Xof for CShake256 {
173 #[inline]
174 fn absorb(&mut self, data: &[u8]) {
175 self.keccak.absorb(data);
176 }
177
178 #[inline]
179 fn squeeze(&mut self, out: &mut [u8]) {
180 self.keccak.squeeze(out);
181 }
182}
183
184#[inline]
187pub(crate) fn left_encode(x: usize) -> EncodedBytes {
188 let bytes = x.to_be_bytes();
189 let first_non_zero = bytes.iter().position(|&b| b != 0).unwrap_or(bytes.len() - 1);
190 let n = bytes.len() - first_non_zero;
191
192 let mut out = Bytes::new();
193 out.push(n as u8);
194 out.append(&bytes[first_non_zero..]);
195 return out;
196}
197
198#[inline]
199pub(crate) fn right_encode(x: usize) -> EncodedBytes {
200 let mut bytes = left_encode(x);
201 let out = bytes.as_mut();
202 let n = out[0];
203 out[0] = out[1];
204 for i in 1..(n as usize) {
205 out[i] = out[i + 1];
206 }
207 out[n as usize] = n;
208 return bytes;
209}
210
211#[cfg(test)]
235mod tests {
236 use super::{CShake256, Shake256};
237 use crate::{Hasher, Xof};
238
239 fn vectors_shake256() -> Vec<(Vec<u8>, usize, &'static str)> {
242 vec![
243 (
244 b"".to_vec(),
245 64,
246 "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be",
247 ),
248 (
249 b"".to_vec(),
250 128,
251 "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be141e96616fb13957692cc7edd0b45ae3dc07223c8e92937bef84bc0eab862853349ec75546f58fb7c2775c38462c5010d846c185c15111e595522a6bcd16cf86",
252 ),
253 (
254 b"abc".to_vec(),
255 64,
256 "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4",
257 ),
258 (
259 b"hello world".to_vec(),
260 64,
261 "369771bb2cb9d2b04c1d54cca487e372d9f187f73f7ba3f65b95c8ee7798c527f4f3c2d55c2d46a29f2e945d469c3df27853a8735271f5cc2d9e889544357116",
262 ),
263 (
264 b"The quick brown fox jumps over the lazy dog".to_vec(),
265 64,
266 "2f671343d9b2e1604dc9dcf0753e5fe15c7c64a0d283cbbf722d411a0e36f6ca1d01d1369a23539cd80f7c054b6e5daf9c962cad5b8ed5bd11998b40d5734442",
267 ),
268 (
269 b"The quick brown fox jumps over the lazy dog.".to_vec(),
270 64,
271 "bd225bfc8b255f3036f0c8866010ed0053b5163a3cae111e723c0c8e704eca4e5d0f1e2a2fa18c8a219de6b88d5917ff5dd75b5fb345e7409a3b333b508a65fb",
272 ),
273 (
274 vec![b'a'; 1_000_000],
275 64,
276 "3578a7a4ca9137569cdf76ed617d31bb994fca9c1bbf8b184013de8234dfd13a3fd124d4df76c0a539ee7dd2f6e1ec346124c815d9410e145eb561bcd97b18ab",
277 ),
278 ]
279 }
280
281 #[test]
282 fn known_vectors() {
283 for (input, output_len, expected) in vectors_shake256() {
284 let mut output = vec![0u8; output_len];
285 Shake256::hash(&input, &mut output);
286 assert_eq!(hex::encode(output), expected);
287 }
288 }
289
290 #[test]
291 fn incremental_and_streaming_read() {
292 let mut one_shot = vec![0u8; 128];
293 Shake256::hash(b"", &mut one_shot);
294
295 let mut shake = Shake256::new();
296 shake.absorb(b"");
297 let mut first = [0u8; 64];
298 let mut second = [0u8; 64];
299 shake.squeeze(&mut first);
300 shake.squeeze(&mut second);
301
302 let mut combined = vec![0u8; 128];
303 combined[..64].copy_from_slice(&first);
304 combined[64..].copy_from_slice(&second);
305
306 assert_eq!(combined, one_shot);
307 }
308
309 #[test]
310 fn hasher_trait_impl() {
311 let expected = "369771bb2cb9d2b04c1d54cca487e372d9f187f73f7ba3f65b95c8ee7798c527f4f3c2d55c2d46a29f2e945d469c3df27853a8735271f5cc2d9e889544357116";
312 let digest = <Shake256 as Hasher>::hash(b"hello world");
313 assert_eq!(hex::encode(digest.as_ref()), expected);
314 }
315
316 #[test]
317 fn xof_trait_impl() {
318 let mut xof = Shake256::new();
319 xof.absorb(b"abc");
320 let mut out = [0u8; 64];
321 xof.squeeze(&mut out);
322 assert_eq!(
323 hex::encode(out),
324 "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4"
325 );
326 }
327
328 const EMAIL_SIGNATURE: &[u8] = b"Email Signature";
331 const SAMPLE_3_EXPECTED: &str = "d008828e2b80ac9d2218ffee1d070c48b8e4c87bff32c9699d5b6896eee0edd164020e2be0560858d9c00c037e34a96937c561a74c412bb4c746469527281c8c";
332 const SAMPLE_4_EXPECTED: &str = "07dc27b11e51fbac75bc7b3c1d983e8b4b85fb1defaf218912ac86430273091727f42b17ed1df63e8ec118f04b23633c1dfb1574c8fb55cb45da8e25afb092bb";
333
334 #[test]
335 fn cshake256_nist_sample_3() {
336 let mut out = [0u8; 64];
337 CShake256::hash(&[0x00, 0x01, 0x02, 0x03], b"", EMAIL_SIGNATURE, &mut out);
338 assert_eq!(hex::encode(out), SAMPLE_3_EXPECTED);
339 }
340
341 #[test]
342 fn cshake256_nist_sample_4() {
343 let input: Vec<u8> = (0u8..200).collect();
344 let mut out = [0u8; 64];
345 CShake256::hash(&input, b"", EMAIL_SIGNATURE, &mut out);
346 assert_eq!(hex::encode(out), SAMPLE_4_EXPECTED);
347 }
348
349 #[test]
350 fn cshake256_incremental_matches_one_shot() {
351 let input: Vec<u8> = (0u8..200).collect();
352 let mut one_shot = [0u8; 64];
353 CShake256::hash(&input, b"", EMAIL_SIGNATURE, &mut one_shot);
354
355 let mut cshake = CShake256::new(b"", EMAIL_SIGNATURE);
356 for chunk in input.chunks(9) {
357 cshake.absorb(chunk);
358 }
359 let mut streamed = [0u8; 64];
360 cshake.squeeze(&mut streamed);
361 assert_eq!(streamed, one_shot);
362 }
363
364 #[test]
365 fn cshake256_empty_params_passes_shake256_vectors() {
366 for (input, output_len, expected) in vectors_shake256() {
367 let mut cshake_out = vec![0u8; output_len];
368 CShake256::hash(&input, b"", b"", &mut cshake_out);
369 assert_eq!(hex::encode(cshake_out), expected);
370 }
371 }
372
373 #[test]
374 fn cshake256_xof_trait_impl() {
375 let mut xof = CShake256::new(b"", b"");
376 xof.absorb(b"abc");
377 let mut out = [0u8; 64];
378 xof.squeeze(&mut out);
379 assert_eq!(
380 hex::encode(out),
381 "483366601360a8771c6863080cc4114d8db44530f8f1e1ee4f94ea37e78b5739d5a15bef186a5386c75744c0527e1faa9f8726e462a12a4feb06bd8801e751e4"
382 );
383 }
384}