1use crate::Hasher;
8use crate::Xof;
9
10const KECCAK_ROUNDS: usize = 24;
15
16const RC: [u64; 24] = [
17 0x0000000000000001,
18 0x0000000000008082,
19 0x800000000000808A,
20 0x8000000080008000,
21 0x000000000000808B,
22 0x0000000080000001,
23 0x8000000080008081,
24 0x8000000000008009,
25 0x000000000000008A,
26 0x0000000000000088,
27 0x0000000080008009,
28 0x000000008000000A,
29 0x000000008000808B,
30 0x800000000000008B,
31 0x8000000000008089,
32 0x8000000000008003,
33 0x8000000000008002,
34 0x8000000000000080,
35 0x000000000000800A,
36 0x800000008000000A,
37 0x8000000080008081,
38 0x8000000000008080,
39 0x0000000080000001,
40 0x8000000080008008,
41];
42
43const ROTC: [u32; 24] = [
44 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
45];
46
47const PI: [usize; 24] = [
48 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
49];
50
51#[inline(always)]
52fn keccak_f(state: &mut [u64; 25]) {
53 for round in 0..KECCAK_ROUNDS {
54 let mut c = [0u64; 5];
56 for x in 0..5 {
57 c[x] = state[x] ^ state[x + 5] ^ state[x + 10] ^ state[x + 15] ^ state[x + 20];
58 }
59 let mut d = [0u64; 5];
60 for x in 0..5 {
61 d[x] = c[(x + 4) % 5] ^ c[(x + 1) % 5].rotate_left(1);
62 }
63 for i in 0..25 {
64 state[i] ^= d[i % 5];
65 }
66
67 let mut last = state[1];
69 for i in 0..24 {
70 let j = PI[i];
71 let temp = state[j];
72 state[j] = last.rotate_left(ROTC[i]);
73 last = temp;
74 }
75
76 for y in (0..25).step_by(5) {
78 let t0 = state[y];
79 let t1 = state[y + 1];
80 let t2 = state[y + 2];
81 let t3 = state[y + 3];
82 let t4 = state[y + 4];
83 state[y] = t0 ^ (!t1 & t2);
84 state[y + 1] = t1 ^ (!t2 & t3);
85 state[y + 2] = t2 ^ (!t3 & t4);
86 state[y + 3] = t3 ^ (!t4 & t0);
87 state[y + 4] = t4 ^ (!t0 & t1);
88 }
89
90 state[0] ^= RC[round];
92 }
93}
94
95#[inline]
96fn state_as_bytes(state: &[u64; 25]) -> &[u8; 200] {
97 unsafe { &*(state.as_ptr() as *const [u8; 200]) }
98}
99
100#[inline]
101fn state_as_bytes_mut(state: &mut [u64; 25]) -> &mut [u8; 200] {
102 unsafe { &mut *(state.as_mut_ptr() as *mut [u8; 200]) }
103}
104
105#[derive(Clone)]
110pub(crate) struct KeccakState {
111 state: [u64; 25],
112 offset: usize,
113 rate: usize,
114 suffix: u8,
115 squeezing: bool,
116}
117
118impl KeccakState {
119 pub(crate) fn new(rate: usize, suffix: u8) -> Self {
120 Self {
121 state: [0u64; 25],
122 offset: 0,
123 rate,
124 suffix,
125 squeezing: false,
126 }
127 }
128
129 pub(crate) fn absorb(&mut self, data: &[u8]) {
130 debug_assert!(!self.squeezing);
131 let mut pos = 0;
132 while pos < data.len() {
133 let block_remaining = self.rate - self.offset;
134 let to_copy = block_remaining.min(data.len() - pos);
135 let state_bytes = state_as_bytes_mut(&mut self.state);
136 for i in 0..to_copy {
137 state_bytes[self.offset + i] ^= data[pos + i];
138 }
139 self.offset += to_copy;
140 pos += to_copy;
141 if self.offset == self.rate {
142 keccak_f(&mut self.state);
143 self.offset = 0;
144 }
145 }
146 }
147
148 fn pad_and_squeeze(&mut self) {
149 if !self.squeezing {
150 let state_bytes = state_as_bytes_mut(&mut self.state);
151 state_bytes[self.offset] ^= self.suffix;
152 state_bytes[self.rate - 1] ^= 0x80;
153 keccak_f(&mut self.state);
154 self.offset = 0;
155 self.squeezing = true;
156 }
157 }
158
159 pub(crate) fn squeeze(&mut self, out: &mut [u8]) {
160 self.pad_and_squeeze();
161 let mut pos = 0;
162 while pos < out.len() {
163 if self.offset == self.rate {
164 keccak_f(&mut self.state);
165 self.offset = 0;
166 }
167 let available = self.rate - self.offset;
168 let to_copy = available.min(out.len() - pos);
169 let state_bytes = state_as_bytes(&self.state);
170 out[pos..pos + to_copy].copy_from_slice(&state_bytes[self.offset..self.offset + to_copy]);
171 self.offset += to_copy;
172 pos += to_copy;
173 }
174 }
175}
176
177#[derive(Clone)]
183pub struct Sha3_224 {
184 state: KeccakState,
185}
186
187impl Hasher for Sha3_224 {
188 const OUTPUT_LEN: usize = 28;
189 const BLOCK_LEN: usize = 144;
190
191 fn new() -> Self {
192 Self {
193 state: KeccakState::new(144, 0x06),
194 }
195 }
196
197 fn update(&mut self, data: &[u8]) {
198 self.state.absorb(data);
199 }
200
201 fn finalize(self) -> Vec<u8> {
202 let mut out = vec![0u8; 28];
203 self.finalize_into(&mut out);
204 out
205 }
206
207 fn finalize_into(mut self, out: &mut [u8]) {
208 let len = out.len().min(28);
209 let mut buf = [0u8; 28];
210 self.state.squeeze(&mut buf);
211 out[..len].copy_from_slice(&buf[..len]);
212 }
213}
214
215#[derive(Clone)]
221pub struct Sha3_256 {
222 state: KeccakState,
223}
224
225impl Hasher for Sha3_256 {
226 const OUTPUT_LEN: usize = 32;
227 const BLOCK_LEN: usize = 136;
228
229 fn new() -> Self {
230 Self {
231 state: KeccakState::new(136, 0x06),
232 }
233 }
234
235 fn update(&mut self, data: &[u8]) {
236 self.state.absorb(data);
237 }
238
239 fn finalize(self) -> Vec<u8> {
240 let mut out = vec![0u8; 32];
241 self.finalize_into(&mut out);
242 out
243 }
244
245 fn finalize_into(mut self, out: &mut [u8]) {
246 let len = out.len().min(32);
247 let mut buf = [0u8; 32];
248 self.state.squeeze(&mut buf);
249 out[..len].copy_from_slice(&buf[..len]);
250 }
251}
252
253#[derive(Clone)]
259pub struct Sha3_384 {
260 state: KeccakState,
261}
262
263impl Hasher for Sha3_384 {
264 const OUTPUT_LEN: usize = 48;
265 const BLOCK_LEN: usize = 104;
266
267 fn new() -> Self {
268 Self {
269 state: KeccakState::new(104, 0x06),
270 }
271 }
272
273 fn update(&mut self, data: &[u8]) {
274 self.state.absorb(data);
275 }
276
277 fn finalize(self) -> Vec<u8> {
278 let mut out = vec![0u8; 48];
279 self.finalize_into(&mut out);
280 out
281 }
282
283 fn finalize_into(mut self, out: &mut [u8]) {
284 let len = out.len().min(48);
285 let mut buf = [0u8; 48];
286 self.state.squeeze(&mut buf);
287 out[..len].copy_from_slice(&buf[..len]);
288 }
289}
290
291#[derive(Clone)]
297pub struct Sha3_512 {
298 state: KeccakState,
299}
300
301impl Hasher for Sha3_512 {
302 const OUTPUT_LEN: usize = 64;
303 const BLOCK_LEN: usize = 72;
304
305 fn new() -> Self {
306 Self {
307 state: KeccakState::new(72, 0x06),
308 }
309 }
310
311 fn update(&mut self, data: &[u8]) {
312 self.state.absorb(data);
313 }
314
315 fn finalize(self) -> Vec<u8> {
316 let mut out = vec![0u8; 64];
317 self.finalize_into(&mut out);
318 out
319 }
320
321 fn finalize_into(mut self, out: &mut [u8]) {
322 let len = out.len().min(64);
323 let mut buf = [0u8; 64];
324 self.state.squeeze(&mut buf);
325 out[..len].copy_from_slice(&buf[..len]);
326 }
327}
328
329#[derive(Clone)]
335pub struct Shake128 {
336 state: KeccakState,
337}
338
339impl Xof for Shake128 {
340 const BLOCK_LEN: usize = 168;
341
342 fn new() -> Self {
343 Self {
344 state: KeccakState::new(168, 0x1f),
345 }
346 }
347
348 fn update(&mut self, data: &[u8]) {
349 self.state.absorb(data);
350 }
351
352 fn squeeze(&mut self, out: &mut [u8]) {
353 self.state.squeeze(out);
354 }
355}
356
357#[derive(Clone)]
363pub struct Shake256 {
364 state: KeccakState,
365}
366
367impl Xof for Shake256 {
368 const BLOCK_LEN: usize = 136;
369
370 fn new() -> Self {
371 Self {
372 state: KeccakState::new(136, 0x1f),
373 }
374 }
375
376 fn update(&mut self, data: &[u8]) {
377 self.state.absorb(data);
378 }
379
380 fn squeeze(&mut self, out: &mut [u8]) {
381 self.state.squeeze(out);
382 }
383}
384
385#[derive(Clone)]
394pub struct CShake128 {
395 state: KeccakState,
396}
397
398impl CShake128 {
399 pub const RATE: usize = 168;
401
402 pub fn new(function_name: &[u8], customization: &[u8]) -> Self {
405 let mut state = KeccakState::new(
406 168,
407 if function_name.is_empty() && customization.is_empty() {
408 0x1F
409 } else {
410 0x04
411 },
412 );
413 if !function_name.is_empty() || !customization.is_empty() {
414 let prefix = cshake_prefix(168, function_name, customization);
415 state.absorb(&prefix);
416 }
417 Self { state }
418 }
419
420 pub fn update(&mut self, data: &[u8]) {
422 self.state.absorb(data);
423 }
424
425 pub fn squeeze(&mut self, out: &mut [u8]) {
427 self.state.squeeze(out);
428 }
429}
430
431#[derive(Clone)]
436pub struct CShake256 {
437 state: KeccakState,
438}
439
440impl CShake256 {
441 pub const RATE: usize = 136;
443
444 pub fn new(function_name: &[u8], customization: &[u8]) -> Self {
447 let mut state = KeccakState::new(
448 136,
449 if function_name.is_empty() && customization.is_empty() {
450 0x1F
451 } else {
452 0x04
453 },
454 );
455 if !function_name.is_empty() || !customization.is_empty() {
456 let prefix = cshake_prefix(136, function_name, customization);
457 state.absorb(&prefix);
458 }
459 Self { state }
460 }
461
462 pub fn update(&mut self, data: &[u8]) {
464 self.state.absorb(data);
465 }
466
467 pub fn squeeze(&mut self, out: &mut [u8]) {
469 self.state.squeeze(out);
470 }
471}
472
473fn cshake_prefix(rate: usize, function_name: &[u8], customization: &[u8]) -> Vec<u8> {
476 let mut buf = Vec::new();
477 let le = left_encode(rate as u64);
479 buf.extend_from_slice(&le);
480 append_encode_string(&mut buf, function_name);
482 append_encode_string(&mut buf, customization);
484 let pad = (rate - (buf.len() % rate)) % rate;
486 buf.extend(core::iter::repeat(0u8).take(pad));
487 buf
488}
489
490fn left_encode(x: u64) -> Vec<u8> {
491 let mut bytes = Vec::new();
492 let be = x.to_be_bytes();
493 let first = be.iter().position(|&b| b != 0).unwrap_or(7);
494 let n = (8 - first) as u8;
495 bytes.push(n);
496 bytes.extend_from_slice(&be[first..]);
497 bytes
498}
499
500fn append_encode_string(out: &mut Vec<u8>, s: &[u8]) {
501 out.extend_from_slice(&left_encode((s.len() as u64) * 8));
502 out.extend_from_slice(s);
503}
504
505#[cfg(test)]
506mod tests {
507 use super::*;
508 use crate::Hasher;
509
510 #[test]
511 fn test_sha3_224_empty() {
512 let digest = Sha3_224::hash(b"");
513 let expected: [u8; 28] = [
514 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, 0xd4, 0x59,
515 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, 0x5b, 0x5a, 0x6b, 0xc7,
516 ];
517 assert_eq!(&digest[..], &expected[..]);
518 }
519
520 #[test]
521 fn test_sha3_224_abc() {
522 let digest = Sha3_224::hash(b"abc");
523 let expected: [u8; 28] = [
524 0xe6, 0x42, 0x82, 0x4c, 0x3f, 0x8c, 0xf2, 0x4a, 0xd0, 0x92, 0x34, 0xee, 0x7d, 0x3c, 0x76, 0x6f, 0xc9, 0xa3,
525 0xa5, 0x16, 0x8d, 0x0c, 0x94, 0xad, 0x73, 0xb4, 0x6f, 0xdf,
526 ];
527 assert_eq!(&digest[..], &expected[..]);
528 }
529
530 #[test]
531 fn test_sha3_256_empty() {
532 let digest = Sha3_256::hash(b"");
533 let expected: [u8; 32] = [
534 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, 0xf5, 0x80,
535 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a,
536 ];
537 assert_eq!(&digest[..], &expected[..]);
538 }
539
540 #[test]
541 fn test_sha3_256_abc() {
542 let digest = Sha3_256::hash(b"abc");
543 let expected: [u8; 32] = [
544 0x3a, 0x98, 0x5d, 0xa7, 0x4f, 0xe2, 0x25, 0xb2, 0x04, 0x5c, 0x17, 0x2d, 0x6b, 0xd3, 0x90, 0xbd, 0x85, 0x5f,
545 0x08, 0x6e, 0x3e, 0x9d, 0x52, 0x5b, 0x46, 0xbf, 0xe2, 0x45, 0x11, 0x43, 0x15, 0x32,
546 ];
547 assert_eq!(&digest[..], &expected[..]);
548 }
549
550 #[test]
551 fn test_sha3_512_empty() {
552 let digest = Sha3_512::hash(b"");
553 let expected_first_8: [u8; 8] = [0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5];
554 assert_eq!(&digest[..8], &expected_first_8[..]);
555 }
556
557 #[test]
558 fn test_sha3_384_abc() {
559 let digest = Sha3_384::hash(b"abc");
560 let expected: [u8; 48] = [
561 0xec, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6f, 0xc9, 0x26, 0x45, 0x9f, 0x58, 0xe2, 0xc6, 0xad, 0x8d, 0xf9, 0xb4,
562 0x73, 0xcb, 0x0f, 0xc0, 0x8c, 0x25, 0x96, 0xda, 0x7c, 0xf0, 0xe4, 0x9b, 0xe4, 0xb2, 0x98, 0xd8, 0x8c, 0xea,
563 0x92, 0x7a, 0xc7, 0xf5, 0x39, 0xf1, 0xed, 0xf2, 0x28, 0x37, 0x6d, 0x25,
564 ];
565 assert_eq!(&digest[..], &expected[..]);
566 }
567
568 #[test]
571 fn test_cshake128_empty_custom_is_shake128() {
572 let data = [0x00u8; 4];
574 let mut cshake = CShake128::new(b"", b"");
575 cshake.update(&data);
576 let mut out1 = [0u8; 32];
577 cshake.squeeze(&mut out1);
578
579 let mut shake = Shake128::new();
580 shake.update(&data);
581 let mut out2 = [0u8; 32];
582 shake.squeeze(&mut out2);
583
584 assert_eq!(out1, out2);
585 }
586
587 #[test]
588 fn test_cshake128_sample1() {
589 let data = [0x00, 0x01, 0x02, 0x03];
592 let mut c = CShake128::new(b"", b"Email Signature");
593 c.update(&data);
594 let mut out = [0u8; 32];
595 c.squeeze(&mut out);
596 let expected: [u8; 32] = [
597 0xC1, 0xC3, 0x69, 0x25, 0xB6, 0x40, 0x9A, 0x04, 0xF1, 0xB5, 0x04, 0xFC, 0xBC, 0xA9, 0xD8, 0x2B, 0x40, 0x17,
598 0x27, 0x7C, 0xB5, 0xED, 0x2B, 0x20, 0x65, 0xFC, 0x1D, 0x38, 0x14, 0xD5, 0xAA, 0xF5,
599 ];
600 assert_eq!(out, expected);
601 }
602
603 #[test]
604 fn test_cshake256_sample1() {
605 let data = [0x00, 0x01, 0x02, 0x03];
608 let mut c = CShake256::new(b"", b"Email Signature");
609 c.update(&data);
610 let mut out = [0u8; 32];
611 c.squeeze(&mut out);
612 let expected: [u8; 32] = [
613 0xD0, 0x08, 0x82, 0x8E, 0x2B, 0x80, 0xAC, 0x9D, 0x22, 0x18, 0xFF, 0xEE, 0x1D, 0x07, 0x0C, 0x48, 0xB8, 0xE4,
614 0xC8, 0x7B, 0xFF, 0x32, 0xC9, 0x69, 0x9D, 0x5B, 0x68, 0x96, 0xEE, 0xE0, 0xED, 0xD1,
615 ];
616 assert_eq!(out, expected);
617 }
618}