elliptic_curve/hash2curve/
hash2field.rs

1//! Traits for hashing to field elements.
2//!
3//! <https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve>
4
5mod expand_msg;
6
7pub use expand_msg::{xmd::*, xof::*, *};
8
9use crate::{Error, Result};
10use generic_array::{typenum::Unsigned, ArrayLength, GenericArray};
11
12/// The trait for helping to convert to a field element.
13pub trait FromOkm {
14    /// The number of bytes needed to convert to a field element.
15    type Length: ArrayLength<u8>;
16
17    /// Convert a byte sequence into a field element.
18    fn from_okm(data: &GenericArray<u8, Self::Length>) -> Self;
19}
20
21/// Convert an arbitrary byte sequence into a field element.
22///
23/// <https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3>
24///
25/// # Errors
26/// See implementors of [`ExpandMsg`] for errors:
27/// - [`ExpandMsgXmd`]
28/// - [`ExpandMsgXof`]
29///
30/// `len_in_bytes = T::Length * out.len()`
31///
32/// [`ExpandMsgXmd`]: crate::hash2field::ExpandMsgXmd
33/// [`ExpandMsgXof`]: crate::hash2field::ExpandMsgXof
34#[doc(hidden)]
35pub fn hash_to_field<'a, E, T>(data: &[&[u8]], domain: &'a [&'a [u8]], out: &mut [T]) -> Result<()>
36where
37    E: ExpandMsg<'a>,
38    T: FromOkm + Default,
39{
40    let len_in_bytes = T::Length::to_usize().checked_mul(out.len()).ok_or(Error)?;
41    let mut tmp = GenericArray::<u8, <T as FromOkm>::Length>::default();
42    let mut expander = E::expand_message(data, domain, len_in_bytes)?;
43    for o in out.iter_mut() {
44        expander.fill_bytes(&mut tmp);
45        *o = T::from_okm(&tmp);
46    }
47    Ok(())
48}