1#[cfg(feature = "alloc")]
25use alloc::vec::Vec;
26
27use crate::constants::{CRYPTO_HASH_SHA3256_BYTES, CRYPTO_HASH_SHA3512_BYTES};
28use crate::keccak::{DOMAIN_SHA3, RATE_256, RATE_512, ROUNDS_FULL, Sponge};
29use crate::types::*;
30
31pub type Digest256 = StackByteArray<CRYPTO_HASH_SHA3256_BYTES>;
33pub type Digest512 = StackByteArray<CRYPTO_HASH_SHA3512_BYTES>;
35
36macro_rules! sha3_hasher {
43 (
44 $(#[$meta:meta])*
45 $name:ident,
46 $algo:literal,
47 $rate:expr,
48 $digest_bytes:expr,
49 ) => {
50 $(#[$meta])*
51 #[derive(Clone)]
52 pub struct $name {
53 sponge: Sponge<$rate, ROUNDS_FULL>,
54 }
55
56 impl $name {
57 #[doc = concat!("Returns a new ", $algo, " hasher instance.")]
58 #[must_use]
59 pub fn new() -> Self {
60 Self {
61 sponge: Sponge::new(),
62 }
63 }
64
65 #[doc = concat!(
66 "One-time interface to compute ",
67 $algo,
68 " digest for `input`, copying\nresult into `output`."
69 )]
70 pub fn compute_into_bytes<Output: MutByteArray<$digest_bytes>, Input: Bytes + ?Sized>(
71 output: &mut Output,
72 input: &Input,
73 ) {
74 let mut hasher = Self::new();
75 hasher.update(input);
76 hasher.finalize_in_place(output.as_mut_array());
77 }
78
79 #[doc = concat!(
80 "One-time interface to compute ",
81 $algo,
82 " digest for `input`."
83 )]
84 #[must_use]
85 pub fn compute<Output: NewByteArray<$digest_bytes>, Input: Bytes + ?Sized>(
86 input: &Input,
87 ) -> Output {
88 let mut hasher = Self::new();
89 hasher.update(input);
90 let mut hash = Output::new_byte_array();
91 hasher.finalize_in_place(hash.as_mut_array());
92 hash
93 }
94
95 #[doc = concat!(
96 "Wrapper around [`",
97 stringify!($name),
98 "::compute`], returning a [`Vec`]. Provided for\nconvenience."
99 )]
100 #[cfg(feature = "alloc")]
101 #[must_use]
102 pub fn compute_to_vec<Input: Bytes + ?Sized>(input: &Input) -> Vec<u8> {
103 Self::compute::<StackByteArray<$digest_bytes>, _>(input).to_vec()
104 }
105
106 #[doc = concat!("Updates ", $algo, " hash state with `input`.")]
107 pub fn update<Input: Bytes + ?Sized>(&mut self, input: &Input) {
108 self.sponge.absorb(input.as_slice())
109 }
110
111 #[must_use]
113 pub fn finalize<Output: NewByteArray<$digest_bytes>>(mut self) -> Output {
114 let mut hash = Output::new_byte_array();
115 self.finalize_in_place(hash.as_mut_array());
116 hash
117 }
118
119 pub fn finalize_into_bytes<Output: MutByteArray<$digest_bytes>>(
121 mut self,
122 output: &mut Output,
123 ) {
124 self.finalize_in_place(output.as_mut_array());
125 }
126
127 #[inline]
133 fn finalize_in_place(&mut self, output: &mut [u8; $digest_bytes]) {
134 self.sponge.pad(DOMAIN_SHA3);
135 self.sponge.squeeze(output);
136 }
137
138 #[cfg(feature = "alloc")]
140 #[must_use]
141 pub fn finalize_to_vec(mut self) -> Vec<u8> {
142 let mut hash = StackByteArray::<$digest_bytes>::default();
143 self.finalize_in_place(hash.as_mut_array());
144 hash.to_vec()
145 }
146 }
147
148 impl Default for $name {
149 fn default() -> Self {
150 Self::new()
151 }
152 }
153 };
154}
155
156sha3_hasher! {
157 Sha3256,
159 "SHA3-256",
160 RATE_256,
161 CRYPTO_HASH_SHA3256_BYTES,
162}
163
164sha3_hasher! {
165 Sha3512,
167 "SHA3-512",
168 RATE_512,
169 CRYPTO_HASH_SHA3512_BYTES,
170}
171
172#[cfg(test)]
182pub(crate) mod test_vectors {
183 pub(crate) use crate::keccak::{RATE_256 as SHA3_256_RATE, RATE_512 as SHA3_512_RATE};
184 use crate::test_prelude::*;
185 use crate::utils::test_util::hex;
186
187 fn pattern(len: usize) -> Vec<u8> {
188 (0..len as u32).map(|i| (i * 31 % 251) as u8).collect()
189 }
190
191 pub(crate) fn sha3_256() -> Vec<(Vec<u8>, Vec<u8>)> {
194 vec![
195 (
196 vec![],
197 hex("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"),
198 ),
199 (
200 b"abc".to_vec(),
201 hex("3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"),
202 ),
203 (
204 hex(concat!(
205 "b771d5cef5d1a41a93d15643d7181d2a2ef0a8e84d91812f20ed21f147bef732",
206 "bf3a60ef4067c3734b85bc8cd471780f10dc9e8291b58339a677b960218f71e7",
207 "93f2797aea349406512829065d37bb55ea796fa4f56fd8896b49b2cd19b43215",
208 "ad967c712b24e5032d065232e02c127409d2ed4146b9d75d763d52db98d949d3",
209 "b0fed6a8052fbb",
210 )),
211 hex("a19eee92bb2097b64e823d597798aa18be9b7c736b8059abfd6779ac35ac81b5"),
212 ),
213 (
214 hex(concat!(
215 "b32d95b0b9aad2a8816de6d06d1f86008505bd8c14124f6e9a163b5a2ade55f8",
216 "35d0ec3880ef50700d3b25e42cc0af050ccd1be5e555b23087e04d7bf9813622",
217 "780c7313a1954f8740b6ee2d3f71f768dd417f520482bd3a08d4f222b4ee9dbd",
218 "015447b33507dd50f3ab4247c5de9a8abd62a8decea01e3b87c8b927f5b08beb",
219 "37674c6f8e380c04",
220 )),
221 hex("df673f4105379ff6b755eeab20ceb0dc77b5286364fe16c59cc8a907aff07732"),
222 ),
223 (
224 hex(concat!(
225 "04410e31082a47584b406f051398a6abe74e4da59bb6f85e6b49e8a1f7f2ca00",
226 "dfba5462c2cd2bfde8b64fb21d70c083f11318b56a52d03b81cac5eec29eb31b",
227 "d0078b6156786da3d6d8c33098c5c47bb67ac64db14165af65b44544d806dde5",
228 "f487d5373c7f9792c299e9686b7e5821e7c8e2458315b996b5677d926dac57b3",
229 "f22da873c601016a0d",
230 )),
231 hex("d52432cf3b6b4b949aa848e058dcd62d735e0177279222e7ac0af8504762faa0"),
232 ),
233 (
234 pattern(2 * SHA3_256_RATE),
235 hex("eff96935ef1690d1f7140a486ef18e2d193baa080205e2a69f3b4a184ca03b7f"),
236 ),
237 #[cfg(not(miri))]
240 (
241 vec![b'a'; 1_000_000],
242 hex("5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1"),
243 ),
244 ]
245 }
246
247 pub(crate) fn sha3_512() -> Vec<(Vec<u8>, Vec<u8>)> {
250 vec![
251 (
252 vec![],
253 hex(concat!(
254 "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6",
255 "15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26",
256 )),
257 ),
258 (
259 b"abc".to_vec(),
260 hex(concat!(
261 "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e",
262 "10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0",
263 )),
264 ),
265 (
266 hex(concat!(
267 "13bd2811f6ed2b6f04ff3895aceed7bef8dcd45eb121791bc194a0f806206bff",
268 "c3b9281c2b308b1a729ce008119dd3066e9378acdcc50a98a82e20738800b6cd",
269 "dbe5fe9694ad6d",
270 )),
271 hex(concat!(
272 "def4ab6cda8839729a03e000846604b17f03c5d5d7ec23c483670a13e11573c1",
273 "e9347a63ec69a5abb21305f9382ecdaaabc6850f92840e86f88f4dabfcd93cc0",
274 )),
275 ),
276 (
277 hex(concat!(
278 "1eed9cba179a009ec2ec5508773dd305477ca117e6d569e66b5f64c6bc64801c",
279 "e25a8424ce4a26d575b8a6fb10ead3fd1992edddeec2ebe7150dc98f63adc323",
280 "7ef57b91397aa8a7",
281 )),
282 hex(concat!(
283 "a3e168b0d6c143ee9e17eae92930b97e6600356b73aebb5d68005dd1d0749445",
284 "1a37052f7b39ff030c1ae1d7efc4e0c3667eb7a76c627ec14354c4f6a796e2c6",
285 )),
286 ),
287 (
288 hex(concat!(
289 "ba5b67b5ec3a3ffae2c19dd8176a2ef75c0cd903725d45c9cb7009a900c0b0ca",
290 "7a2967a95ae68269a6dbf8466c7b6844a1d608ac661f7eff00538e323db5f2c6",
291 "44b78b2d48de1a08aa",
292 )),
293 hex(concat!(
294 "635741b37f66cd5ce4dbd1f78accd907f96146e770b239046afb9181910b612d",
295 "0e65841ff866806eed83c3ae7012fc55e42c3ffc9c6e3d03ce2870442f293ab4",
296 )),
297 ),
298 (
299 hex(concat!(
300 "157d5b7e4507f66d9a267476d33831e7bb768d4d04cc3438da12f9010263ea5f",
301 "cafbde2579db2f6b58f911d593d5f79fb05fe3596e3fa80ff2f761d1b0e57080",
302 "055c118c53e53cdb63055261d7c9b2b39bd90acc32520cbbdbda2c4fd8856dbc",
303 "ee173132a2679198daf83007a9b5c51511ae49766c792a29520388444ebefe28",
304 "256fb33d4260439cba73a9479ee00c63",
305 )),
306 hex(concat!(
307 "fe45289874879720ce2a844ae34bb73522775dcb6019dcd22b8885994672a088",
308 "9c69e8115c641dc8b83e39f7311815a164dc46e0ba2fca344d86d4bc2ef2532c",
309 )),
310 ),
311 #[cfg(not(miri))]
312 (
313 vec![b'a'; 1_000_000],
314 hex(concat!(
315 "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859",
316 "ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87",
317 )),
318 ),
319 ]
320 }
321}
322
323#[cfg(all(test, feature = "alloc"))]
324mod tests {
325 use super::test_vectors::*;
326 use super::*;
327
328 #[test]
332 fn test_sha3256_known_answers() {
333 for (message, expected) in sha3_256() {
334 let len = message.len();
335 assert_eq!(Sha3256::compute_to_vec(&message), expected, "len {len}");
336 let mut digest = Digest256::default();
337 Sha3256::compute_into_bytes(&mut digest, &message);
338 assert_eq!(digest.as_slice(), expected, "len {len}");
339
340 let mut state = Sha3256::new();
341 for chunk in message.chunks(SHA3_256_RATE) {
342 state.update(chunk);
343 }
344 assert_eq!(state.finalize_to_vec(), expected, "rate chunks, len {len}");
345 }
346 }
347
348 #[test]
349 fn test_sha3512_known_answers() {
350 for (message, expected) in sha3_512() {
351 let len = message.len();
352 assert_eq!(Sha3512::compute_to_vec(&message), expected, "len {len}");
353 let mut digest = Digest512::default();
354 Sha3512::compute_into_bytes(&mut digest, &message);
355 assert_eq!(digest.as_slice(), expected, "len {len}");
356
357 let mut state = Sha3512::new();
358 for chunk in message.chunks(SHA3_512_RATE) {
359 state.update(chunk);
360 }
361 assert_eq!(state.finalize_to_vec(), expected, "rate chunks, len {len}");
362 }
363 }
364
365 #[test]
368 fn test_byte_and_empty_updates_match_known_answers() {
369 for (message, expected) in sha3_256()
370 .into_iter()
371 .filter(|(m, _)| m.len() <= 2 * SHA3_256_RATE)
372 {
373 let mut state = Sha3256::new();
374 state.update(b"");
375 for byte in &message {
376 state.update(core::slice::from_ref(byte));
377 state.update(b"");
378 }
379 assert_eq!(state.finalize_to_vec(), expected, "len {}", message.len());
380 }
381 for (message, expected) in sha3_512()
382 .into_iter()
383 .filter(|(m, _)| m.len() <= 2 * SHA3_512_RATE)
384 {
385 let mut state = Sha3512::new();
386 state.update(b"");
387 for byte in &message {
388 state.update(core::slice::from_ref(byte));
389 state.update(b"");
390 }
391 assert_eq!(state.finalize_to_vec(), expected, "len {}", message.len());
392 }
393 }
394}