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> {
43 expander: ExpanderXmd<H>,
44 len_per_base_elem: usize,
45}
46
47impl<F: Field, H: FixedOutputReset + Default + Clone, const SEC_PARAM: usize> HashToField<F>
48 for DefaultFieldHasher<H, SEC_PARAM>
49{
50 fn new(dst: &[u8]) -> Self {
51 let len_per_base_elem = get_len_per_elem::<F, SEC_PARAM>();
54
55 let expander = ExpanderXmd {
56 hasher: PhantomData,
57 dst: dst.to_vec(),
58 block_size: len_per_base_elem,
59 };
60
61 DefaultFieldHasher {
62 expander,
63 len_per_base_elem,
64 }
65 }
66
67 fn hash_to_field<const N: usize>(&self, message: &[u8]) -> [F; N] {
68 let m = F::extension_degree() as usize;
69
70 let len_in_bytes = N * m * self.len_per_base_elem;
73 let uniform_bytes = self.expander.expand(message, len_in_bytes);
74
75 let cb = |i| {
76 let base_prime_field_elem = |j| {
77 let elm_offset = self.len_per_base_elem * (j + i * m);
78 F::BasePrimeField::from_be_bytes_mod_order(
79 &uniform_bytes[elm_offset..][..self.len_per_base_elem],
80 )
81 };
82 F::from_base_prime_field_elems((0..m).map(base_prime_field_elem)).unwrap()
83 };
84 ark_std::array::from_fn(cb)
85 }
86}
87
88pub fn hash_to_field<F: Field, H: XofReader, const SEC_PARAM: usize>(h: &mut H) -> F {
89 let len_per_base_elem = get_len_per_elem::<F, SEC_PARAM>();
92 let mut alloca = [0u8; 2048];
94 let alloca = &mut alloca[0..len_per_base_elem];
95
96 let m = F::extension_degree() as usize;
97
98 let base_prime_field_elem = |_| {
99 h.read(alloca);
100 F::BasePrimeField::from_be_bytes_mod_order(alloca)
101 };
102 F::from_base_prime_field_elems((0..m).map(base_prime_field_elem)).unwrap()
103}
104
105const fn get_len_per_elem<F: Field, const SEC_PARAM: usize>() -> usize {
110 let base_field_size_in_bits = F::BasePrimeField::MODULUS_BIT_SIZE as usize;
112 let base_field_size_with_security_padding_in_bits = base_field_size_in_bits + SEC_PARAM;
114 let bytes_per_base_field_elem =
116 base_field_size_with_security_padding_in_bits.div_ceil(8) as u64;
117 bytes_per_base_field_elem as usize
118}