snarkvm_console_algorithms/keccak/
hash.rs1use super::*;
17use snarkvm_utilities::{bits_from_bytes_le, bytes_from_bits_le};
18
19impl<const TYPE: u8, const VARIANT: usize> Hash for Keccak<TYPE, VARIANT> {
20    type Input = bool;
21    type Output = Vec<bool>;
22
23    #[inline]
25    fn hash(&self, input: &[Self::Input]) -> Result<Self::Output> {
26        let result = match (TYPE, VARIANT) {
27            (0, 224) => bits_from_bytes_le(&keccak_224_native(&bytes_from_bits_le(input))).collect(),
28            (0, 256) => bits_from_bytes_le(&keccak_256_native(&bytes_from_bits_le(input))).collect(),
29            (0, 384) => bits_from_bytes_le(&keccak_384_native(&bytes_from_bits_le(input))).collect(),
30            (0, 512) => bits_from_bytes_le(&keccak_512_native(&bytes_from_bits_le(input))).collect(),
31            (1, 224) => bits_from_bytes_le(&sha3_224_native(&bytes_from_bits_le(input))).collect(),
32            (1, 256) => bits_from_bytes_le(&sha3_256_native(&bytes_from_bits_le(input))).collect(),
33            (1, 384) => bits_from_bytes_le(&sha3_384_native(&bytes_from_bits_le(input))).collect(),
34            (1, 512) => bits_from_bytes_le(&sha3_512_native(&bytes_from_bits_le(input))).collect(),
35            _ => unreachable!("Invalid Keccak type and variant"),
36        };
37        Ok(result)
38    }
39}
40
41fn keccak_224_native(preimage: &[u8]) -> [u8; 28] {
43    let mut keccak = TinyKeccak::v224();
44    keccak.update(preimage);
45
46    let mut hash = [0u8; 28];
47    keccak.finalize(&mut hash);
48    hash
49}
50
51fn keccak_256_native(preimage: &[u8]) -> [u8; 32] {
53    let mut keccak = TinyKeccak::v256();
54    keccak.update(preimage);
55
56    let mut hash = [0u8; 32];
57    keccak.finalize(&mut hash);
58    hash
59}
60
61fn keccak_384_native(preimage: &[u8]) -> [u8; 48] {
63    let mut keccak = TinyKeccak::v384();
64    keccak.update(preimage);
65
66    let mut hash = [0u8; 48];
67    keccak.finalize(&mut hash);
68    hash
69}
70
71fn keccak_512_native(preimage: &[u8]) -> [u8; 64] {
73    let mut keccak = TinyKeccak::v512();
74    keccak.update(preimage);
75
76    let mut hash = [0u8; 64];
77    keccak.finalize(&mut hash);
78    hash
79}
80
81fn sha3_224_native(preimage: &[u8]) -> [u8; 28] {
83    let mut keccak = TinySha3::v224();
84    keccak.update(preimage);
85
86    let mut hash = [0u8; 28];
87    keccak.finalize(&mut hash);
88    hash
89}
90
91fn sha3_256_native(preimage: &[u8]) -> [u8; 32] {
93    let mut keccak = TinySha3::v256();
94    keccak.update(preimage);
95
96    let mut hash = [0u8; 32];
97    keccak.finalize(&mut hash);
98    hash
99}
100
101fn sha3_384_native(preimage: &[u8]) -> [u8; 48] {
103    let mut keccak = TinySha3::v384();
104    keccak.update(preimage);
105
106    let mut hash = [0u8; 48];
107    keccak.finalize(&mut hash);
108    hash
109}
110
111fn sha3_512_native(preimage: &[u8]) -> [u8; 64] {
113    let mut keccak = TinySha3::v512();
114    keccak.update(preimage);
115
116    let mut hash = [0u8; 64];
117    keccak.finalize(&mut hash);
118    hash
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124    use crate::Rng;
125    use snarkvm_utilities::{bits_from_bytes_le, bytes_from_bits_le};
126
127    macro_rules! check_equivalence {
128        ($console:expr, $native:expr) => {
129            let rng = &mut TestRng::default();
130
131            let mut input_sizes = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 32, 64, 128, 256, 512, 1024];
132            input_sizes.extend((0..100).map(|_| rng.gen_range(1..1024)));
133
134            for num_inputs in input_sizes {
135                println!("Checking equivalence for {num_inputs} inputs");
136
137                let input = (0..num_inputs).map(|_| Uniform::rand(rng)).collect::<Vec<bool>>();
139
140                let expected = $native(&bytes_from_bits_le(&input));
142                let expected = bits_from_bytes_le(&expected).collect::<Vec<_>>();
143
144                let candidate = $console.hash(&input).unwrap();
146                assert_eq!(expected, candidate);
147            }
148        };
149    }
150
151    #[test]
152    fn test_keccak_224_equivalence() {
153        check_equivalence!(Keccak224::default(), keccak_224_native);
154    }
155
156    #[test]
157    fn test_keccak_256_equivalence() {
158        check_equivalence!(Keccak256::default(), keccak_256_native);
159    }
160
161    #[test]
162    fn test_keccak_384_equivalence() {
163        check_equivalence!(Keccak384::default(), keccak_384_native);
164    }
165
166    #[test]
167    fn test_keccak_512_equivalence() {
168        check_equivalence!(Keccak512::default(), keccak_512_native);
169    }
170
171    #[test]
172    fn test_sha3_224_equivalence() {
173        check_equivalence!(Sha3_224::default(), sha3_224_native);
174    }
175
176    #[test]
177    fn test_sha3_256_equivalence() {
178        check_equivalence!(Sha3_256::default(), sha3_256_native);
179    }
180
181    #[test]
182    fn test_sha3_384_equivalence() {
183        check_equivalence!(Sha3_384::default(), sha3_384_native);
184    }
185
186    #[test]
187    fn test_sha3_512_equivalence() {
188        check_equivalence!(Sha3_512::default(), sha3_512_native);
189    }
190}