1use super::keccak::Keccak;
2use crate::{Hash, Hasher};
3
4const SHA3_256_RATE: usize = 136;
5const SHA3_256_DOMAIN_SEPARATOR: u8 = 0x06;
6
7#[derive(Clone)]
8#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
9pub struct Sha3_256 {
10 keccak: Keccak<24>,
11}
12
13impl Sha3_256 {
14 #[inline]
15 pub fn new() -> Self {
16 return Sha3_256 {
17 keccak: Keccak::new(SHA3_256_RATE, SHA3_256_DOMAIN_SEPARATOR),
18 };
19 }
20
21 #[inline]
22 pub fn write(&mut self, data: &[u8]) {
23 self.keccak.absorb(data);
24 }
25
26 #[inline]
27 pub fn sum(mut self) -> [u8; 32] {
28 let mut output = [0u8; 32];
29 self.keccak.squeeze(&mut output);
30 return output;
31 }
32}
33
34impl Hasher for Sha3_256 {
35 const BLOCK_SIZE: usize = SHA3_256_RATE;
36 const OUTPUT_SIZE: usize = 32;
37
38 #[inline]
39 fn new() -> Self {
40 return Sha3_256::new();
41 }
42
43 #[inline]
44 fn update(&mut self, data: &[u8]) {
45 self.write(data);
46 }
47
48 #[inline]
49 fn sum(mut self) -> Hash {
50 let mut hash = Hash::with_length(Self::OUTPUT_SIZE);
51 self.keccak.squeeze(hash.as_mut());
52 return hash;
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::Sha3_256;
59 use crate::Hasher;
60
61 fn vectors_sha3_256() -> Vec<(Vec<u8>, &'static str)> {
62 vec![
63 (b"".to_vec(), "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"),
64 (
65 b"abc".to_vec(),
66 "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532",
67 ),
68 (
69 b"hello world".to_vec(),
70 "644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938",
71 ),
72 (
73 b"The quick brown fox jumps over the lazy dog".to_vec(),
74 "69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04",
75 ),
76 (
77 b"The quick brown fox jumps over the lazy dog.".to_vec(),
78 "a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d",
79 ),
80 (
81 vec![b'a'; 1_000_000],
82 "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1",
83 ),
84 ]
85 }
86
87 #[test]
88 fn known_vectors_single_update() {
89 for (input, expected) in vectors_sha3_256() {
90 assert_eq!(hex::encode(Sha3_256::hash(&input)), expected);
91 }
92 }
93
94 #[test]
95 fn known_vectors_incremental() {
96 for (input, expected) in vectors_sha3_256() {
97 let mut sha3_256 = Sha3_256::new();
98 for chunk in input.chunks(7) {
99 sha3_256.write(chunk);
100 }
101 assert_eq!(hex::encode(sha3_256.sum()), expected);
102 }
103 }
104
105 #[test]
106 fn hasher_trait_impl() {
107 for (input, expected) in vectors_sha3_256() {
108 let digest = <Sha3_256 as Hasher>::hash(&input);
109 assert_eq!(hex::encode(digest.as_ref()), expected);
110 }
111 }
112}