Skip to main content

crypto/sha3/
sha3_256.rs

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}