Skip to main content

crypto/sha3/
sha3_512.rs

1use super::keccak::KeccakSponge;
2use crate::{Bytes, Hash, Hasher};
3
4const SHA3_512_RATE: usize = 72;
5const SHA3_512_DOMAIN_SEPARATOR: u8 = 0x06;
6
7/// SHA3-512 hash function (FIPS 202).
8///
9/// Implements the [`Hasher`] trait.
10///
11/// # One-shot API
12///
13/// ```ignore
14/// use crypto::{Hasher, sha3::Sha3_512};
15///
16/// let hash = Sha3_512::hash(b"hello world");
17/// ```
18///
19/// # Incremental API
20///
21/// ```ignore
22/// use crypto::{Hasher, sha3::Sha3_512};
23///
24/// let mut hasher = Sha3_512::new();
25/// hasher.update(b"hello ");
26/// hasher.update(b"world");
27/// let hash = hasher.sum();
28/// ```
29#[derive(Clone)]
30#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize, zeroize::ZeroizeOnDrop))]
31pub struct Sha3_512 {
32    keccak: KeccakSponge<24>,
33}
34
35impl Hasher for Sha3_512 {
36    const BLOCK_SIZE: usize = SHA3_512_RATE;
37    const OUTPUT_SIZE: usize = 64;
38
39    #[inline]
40    fn new() -> Self {
41        Sha3_512 {
42            keccak: KeccakSponge::new(SHA3_512_RATE, SHA3_512_DOMAIN_SEPARATOR),
43        }
44    }
45
46    #[inline]
47    fn update(&mut self, data: &[u8]) {
48        self.keccak.absorb(data);
49    }
50
51    #[inline]
52    fn sum(mut self) -> Hash {
53        let mut hash = Bytes::<64>::with_length(Self::OUTPUT_SIZE);
54        self.keccak.squeeze(hash.as_mut());
55        return Hash(hash);
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::Sha3_512;
62    use crate::Hasher;
63
64    fn vectors_sha3_512() -> Vec<(Vec<u8>, &'static str)> {
65        vec![
66            (
67                b"".to_vec(),
68                "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26",
69            ),
70            (
71                b"abc".to_vec(),
72                "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0",
73            ),
74            (
75                b"hello world".to_vec(),
76                "840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a",
77            ),
78            (
79                b"The quick brown fox jumps over the lazy dog".to_vec(),
80                "01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450",
81            ),
82            (
83                b"The quick brown fox jumps over the lazy dog.".to_vec(),
84                "18f4f4bd419603f95538837003d9d254c26c23765565162247483f65c50303597bc9ce4d289f21d1c2f1f458828e33dc442100331b35e7eb031b5d38ba6460f8",
85            ),
86            (
87                vec![b'a'; 1_000_000],
88                "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87",
89            ),
90        ]
91    }
92
93    #[test]
94    fn known_vectors_single_update() {
95        for (input, expected) in vectors_sha3_512() {
96            assert_eq!(hex::encode(<Sha3_512 as Hasher>::hash(&input)), expected);
97        }
98    }
99
100    #[test]
101    fn known_vectors_incremental() {
102        for (input, expected) in vectors_sha3_512() {
103            let mut sha3_512 = <Sha3_512 as Hasher>::new();
104            for chunk in input.chunks(11) {
105                sha3_512.update(chunk);
106            }
107            assert_eq!(hex::encode(&sha3_512.sum()), expected);
108        }
109    }
110
111    #[test]
112    fn hasher_trait_impl() {
113        for (input, expected) in vectors_sha3_512() {
114            let digest = <Sha3_512 as Hasher>::hash(&input);
115            assert_eq!(hex::encode(&digest), expected);
116        }
117    }
118}