webb_pedersen_hash/
lib.rs

1use std::convert::TryInto;
2
3use ark_crypto_primitives::crh::{
4    injective_map::{PedersenCRHCompressor, TECompressor},
5    pedersen, CRH,
6};
7use ark_crypto_primitives::Error;
8use ark_ed_on_bn254::EdwardsProjective;
9use ark_ff::{fields::PrimeField, BigInteger};
10use rand_chacha::rand_core::SeedableRng;
11
12pub type PedersenHasher =
13    PedersenCRHCompressor<EdwardsProjective, TECompressor, PedersenWindow>;
14
15#[derive(Clone, PartialEq, Eq, Hash)]
16pub struct PedersenWindow;
17
18const MAX_INPUT_SIZE: usize = 64;
19
20impl pedersen::Window for PedersenWindow {
21    const WINDOW_SIZE: usize = 4;
22    const NUM_WINDOWS: usize = (8 * MAX_INPUT_SIZE) / Self::WINDOW_SIZE;
23}
24
25pub fn hash(data: &[u8]) -> Result<[u8; 32], Error> {
26    const SEED: &[u8; 32] = b"WebbToolsPedersenHasherSeedBytes";
27    let mut rng = rand_chacha::ChaChaRng::from_seed(*SEED);
28    let crh_params = PedersenHasher::setup(&mut rng)?;
29    let result = PedersenHasher::evaluate(&crh_params, data)?;
30    let hash = result
31        .into_repr()
32        .to_bytes_be() // always use big-endian for bignumbers!!
33        .try_into()
34        .expect("Hash is always 32 bytes!");
35    Ok(hash)
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn should_hash_data() {
44        let data = b"Pedersen";
45        let out = hash(data).unwrap();
46        let actual =
47            "0293c0b3986c951148d89e12edb706c0e40df4b6b6510e9392eff2ab2f7092ad";
48        assert_eq!(hex::encode(out), actual);
49    }
50}