ark_ff/fields/field_hashers/
mod.rs1mod expander;
2
3use core::marker::PhantomData;
4
5use crate::{Field, PrimeField};
6
7use digest::{FixedOutputReset, XofReader};
8use expander::Expander;
9
10use self::expander::ExpanderXmd;
11
12pub trait HashToField<F: Field>: Sized {
14 fn new(domain: &[u8]) -> Self;
20
21 fn hash_to_field<const N: usize>(&self, msg: &[u8]) -> [F; N];
23}
24
25pub struct DefaultFieldHasher<H: FixedOutputReset + Default + Clone, const SEC_PARAM: usize = 128> {
42 expander: ExpanderXmd<H>,
43 len_per_base_elem: usize,
44}
45
46impl<F: Field, H: FixedOutputReset + Default + Clone, const SEC_PARAM: usize> HashToField<F>
47 for DefaultFieldHasher<H, SEC_PARAM>
48{
49 fn new(dst: &[u8]) -> Self {
50 let len_per_base_elem = get_len_per_elem::<F, SEC_PARAM>();
53
54 let expander = ExpanderXmd {
55 hasher: PhantomData,
56 dst: dst.to_vec(),
57 block_size: len_per_base_elem,
58 };
59
60 DefaultFieldHasher {
61 expander,
62 len_per_base_elem,
63 }
64 }
65
66 fn hash_to_field<const N: usize>(&self, message: &[u8]) -> [F; N] {
67 let m = F::extension_degree() as usize;
68
69 let len_in_bytes = N * m * self.len_per_base_elem;
72 let uniform_bytes = self.expander.expand(message, len_in_bytes);
73
74 let cb = |i| {
75 let base_prime_field_elem = |j| {
76 let elm_offset = self.len_per_base_elem * (j + i * m);
77 F::BasePrimeField::from_be_bytes_mod_order(
78 &uniform_bytes[elm_offset..][..self.len_per_base_elem],
79 )
80 };
81 F::from_base_prime_field_elems((0..m).map(base_prime_field_elem)).unwrap()
82 };
83 ark_std::array::from_fn::<F, N, _>(cb)
84 }
85}
86
87pub fn hash_to_field<F: Field, H: XofReader, const SEC_PARAM: usize>(h: &mut H) -> F {
88 let len_per_base_elem = get_len_per_elem::<F, SEC_PARAM>();
91 let mut alloca = [0u8; 2048];
93 let alloca = &mut alloca[0..len_per_base_elem];
94
95 let m = F::extension_degree() as usize;
96
97 let base_prime_field_elem = |_| {
98 h.read(alloca);
99 F::BasePrimeField::from_be_bytes_mod_order(alloca)
100 };
101 F::from_base_prime_field_elems((0..m).map(base_prime_field_elem)).unwrap()
102}
103
104const fn get_len_per_elem<F: Field, const SEC_PARAM: usize>() -> usize {
109 let base_field_size_in_bits = F::BasePrimeField::MODULUS_BIT_SIZE as usize;
111 let base_field_size_with_security_padding_in_bits = base_field_size_in_bits + SEC_PARAM;
113 let bytes_per_base_field_elem =
115 ((base_field_size_with_security_padding_in_bits + 7) / 8) as u64;
116 bytes_per_base_field_elem as usize
117}