1use sha3::{Digest, Sha3_256, Sha3_512};
9
10use crate::contract::{Hasher, Identified};
11use crate::error::Result;
12
13#[derive(Debug, Default, Clone, Copy)]
15pub struct Sha3_256Hasher;
16
17impl Sha3_256Hasher {
18 pub const IDENTIFIER: &'static str = "sha3-256";
19
20 pub fn new() -> Self {
21 Self
22 }
23}
24
25impl Identified for Sha3_256Hasher {
26 fn identifier(&self) -> &str {
27 Self::IDENTIFIER
28 }
29}
30
31impl Hasher for Sha3_256Hasher {
32 fn digest(&self, data: &[u8]) -> Result<Vec<u8>> {
33 Ok(Sha3_256::digest(data).to_vec())
34 }
35}
36
37#[derive(Debug, Default, Clone, Copy)]
39pub struct Sha3_512Hasher;
40
41impl Sha3_512Hasher {
42 pub const IDENTIFIER: &'static str = "sha3-512";
43
44 pub fn new() -> Self {
45 Self
46 }
47}
48
49impl Identified for Sha3_512Hasher {
50 fn identifier(&self) -> &str {
51 Self::IDENTIFIER
52 }
53}
54
55impl Hasher for Sha3_512Hasher {
56 fn digest(&self, data: &[u8]) -> Result<Vec<u8>> {
57 Ok(Sha3_512::digest(data).to_vec())
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
67 fn matches_nist_example_vectors() {
68 assert_eq!(
69 Sha3_256Hasher::new().digest_hex(b"abc").unwrap(),
70 "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"
71 );
72 assert_eq!(
73 Sha3_512Hasher::new().digest_hex(b"abc").unwrap(),
74 "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e\
75 10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"
76 );
77 assert_eq!(Sha3_256Hasher::new().digest(b"abc").unwrap().len(), 32);
78 assert_eq!(Sha3_512Hasher::new().digest(b"abc").unwrap().len(), 64);
79 }
80
81 #[test]
83 fn digest_hex_is_lowercase_hex() {
84 let hex = Sha3_256Hasher::new().digest_hex(b"abc").unwrap();
85 assert_eq!(hex.len(), 64);
86 assert!(
87 hex.bytes()
88 .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
89 );
90
91 let hex = Sha3_512Hasher::new().digest_hex(b"abc").unwrap();
92 assert_eq!(hex.len(), 128);
93 assert!(
94 hex.bytes()
95 .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase())
96 );
97 }
98
99 #[test]
101 fn distinct_inputs_distinct_digests() {
102 let hasher = Sha3_256Hasher::new();
103 assert_ne!(
104 hasher.digest(b"abc").unwrap(),
105 hasher.digest(b"abd").unwrap()
106 );
107
108 let hasher = Sha3_512Hasher::new();
109 assert_ne!(
110 hasher.digest(b"abc").unwrap(),
111 hasher.digest(b"abd").unwrap()
112 );
113 }
114}