1 //! `expand_message` interface `for hash_to_field`.
6 use crate::{Error, Result}
;
7 use digest
::{Digest, ExtendableOutput, Update, XofReader}
;
8 use generic_array
::typenum
::{IsLess, U256}
;
9 use generic_array
::{ArrayLength, GenericArray}
;
11 /// Salt when the DST is too long
12 const OVERSIZE_DST_SALT
: &[u8] = b
"H2C-OVERSIZE-DST-";
13 /// Maximum domain separation tag length
14 const MAX_DST_LEN
: usize = 255;
16 /// Trait for types implementing expand_message interface for `hash_to_field`.
19 /// See implementors of [`ExpandMsg`] for errors.
20 pub trait ExpandMsg
<'a
> {
21 /// Type holding data for the [`Expander`].
22 type Expander
: Expander
+ Sized
;
24 /// Expands `msg` to the required number of bytes.
26 /// Returns an expander that can be used to call `read` until enough
27 /// bytes have been consumed
28 fn expand_message(msgs
: &[&[u8]], dst
: &'a
[u8], len_in_bytes
: usize)
29 -> Result
<Self::Expander
>;
32 /// Expander that, call `read` until enough bytes have been consumed.
34 /// Fill the array with the expanded bytes
35 fn fill_bytes(&mut self, okm
: &mut [u8]);
38 /// The domain separation tag
40 /// Implements [section 5.4.3 of `draft-irtf-cfrg-hash-to-curve-13`][dst].
42 /// [dst]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-13#section-5.4.3
43 pub(crate) enum Domain
<'a
, L
>
45 L
: ArrayLength
<u8> + IsLess
<U256
>,
48 Hashed(GenericArray
<u8, L
>),
53 impl<'a
, L
> Domain
<'a
, L
>
55 L
: ArrayLength
<u8> + IsLess
<U256
>,
57 pub fn xof
<X
>(dst
: &'a
[u8]) -> Result
<Self>
59 X
: Default
+ ExtendableOutput
+ Update
,
63 } else if dst
.len() > MAX_DST_LEN
{
64 let mut data
= GenericArray
::<u8, L
>::default();
66 .chain(OVERSIZE_DST_SALT
)
70 Ok(Self::Hashed(data
))
76 pub fn xmd
<X
>(dst
: &'a
[u8]) -> Result
<Self>
78 X
: Digest
<OutputSize
= L
>,
82 } else if dst
.len() > MAX_DST_LEN
{
84 let mut hash
= X
::new();
85 hash
.update(OVERSIZE_DST_SALT
);
94 pub fn data(&self) -> &[u8] {
96 Self::Hashed(d
) => &d
[..],
101 pub fn len(&self) -> u8 {
103 // Can't overflow because it's enforced on a type level.
104 Self::Hashed(_
) => L
::to_u8(),
105 // Can't overflow because it's checked on creation.
106 Self::Array(d
) => u8::try_from(d
.len()).expect("length overflow"),
111 pub fn assert(&self, bytes
: &[u8]) {
112 assert_eq
!(self.data(), &bytes
[..bytes
.len() - 1]);
113 assert_eq
!(self.len(), bytes
[bytes
.len() - 1]);