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