Skip to content

Commit 6e1411a

Browse files
committed
Apply constraints and some improvements
1 parent 32c3072 commit 6e1411a

File tree

3 files changed

+45
-25
lines changed

3 files changed

+45
-25
lines changed

elliptic-curve/src/hash2field/expand_msg.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::Result;
2-
use digest::{Digest, ExtendableOutputDirty, Update, XofReader};
2+
use digest::{Digest, ExtendableOutput, Update, XofReader};
3+
use generic_array::typenum::{IsLess, U256};
34
use generic_array::{ArrayLength, GenericArray};
45

56
/// Salt when the DST is too long
@@ -23,24 +24,30 @@ pub trait ExpandMsg: Sized {
2324
/// Implements [section 5.4.3 of `draft-irtf-cfrg-hash-to-curve-13`][dst].
2425
///
2526
/// [dst]: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-13#section-5.4.3
26-
pub(crate) enum Domain<L: ArrayLength<u8>> {
27+
pub(crate) enum Domain<L>
28+
where
29+
L: ArrayLength<u8> + IsLess<U256>,
30+
{
2731
/// > 255
2832
Hashed(GenericArray<u8, L>),
2933
/// <= 255
3034
Array(&'static [u8]),
3135
}
3236

33-
impl<L: ArrayLength<u8>> Domain<L> {
37+
impl<L> Domain<L>
38+
where
39+
L: ArrayLength<u8> + IsLess<U256>,
40+
{
3441
pub fn xof<X>(dst: &'static [u8]) -> Self
3542
where
36-
X: Default + ExtendableOutputDirty + Update,
43+
X: Default + ExtendableOutput + Update,
3744
{
3845
if dst.len() > MAX_DST_LEN {
3946
let mut data = GenericArray::<u8, L>::default();
4047
X::default()
4148
.chain(OVERSIZE_DST_SALT)
4249
.chain(dst)
43-
.finalize_xof_dirty()
50+
.finalize_xof()
4451
.read(&mut data);
4552
Self::Hashed(data)
4653
} else {
@@ -66,10 +73,12 @@ impl<L: ArrayLength<u8>> Domain<L> {
6673
}
6774
}
6875

69-
pub fn len(&self) -> usize {
76+
pub fn len(&self) -> u8 {
7077
match self {
71-
Self::Hashed(_) => L::to_usize(),
72-
Self::Array(d) => d.len(),
78+
// Can't overflow because it's enforced on a type level.
79+
Self::Hashed(_) => L::to_u8(),
80+
// Can't overflow because it's checked on creation.
81+
Self::Array(d) => d.len() as u8,
7382
}
7483
}
7584
}

elliptic-curve/src/hash2field/expand_msg_xmd.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ where
1818
b_0: GenericArray<u8, HashT::OutputSize>,
1919
b_vals: GenericArray<u8, HashT::OutputSize>,
2020
domain: Domain<HashT::OutputSize>,
21-
index: usize,
21+
index: u8,
2222
offset: usize,
23-
ell: usize,
23+
ell: u8,
2424
}
2525

2626
impl<HashT> ExpandMsgXmd<HashT>
@@ -42,9 +42,9 @@ where
4242
.for_each(|(j, (b0val, bi1val))| tmp[j] = b0val ^ bi1val);
4343
self.b_vals = HashT::new()
4444
.chain(tmp)
45-
.chain([self.index as u8])
45+
.chain([self.index])
4646
.chain(self.domain.data())
47-
.chain([self.domain.len() as u8])
47+
.chain([self.domain.len()])
4848
.finalize();
4949
true
5050
} else {
@@ -57,34 +57,39 @@ where
5757
impl<HashT> ExpandMsg for ExpandMsgXmd<HashT>
5858
where
5959
HashT: Digest + BlockInput,
60-
HashT::OutputSize: IsLess<U256> + IsLessOrEqual<HashT::BlockSize>,
60+
// If `len_in_bytes` is bigger then 256, length of the `DST` will depend on
61+
// the output size of the hash, which is still not allowed to be bigger then 256:
62+
// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html#section-5.4.1-6
63+
HashT::OutputSize: IsLess<U256>,
64+
// Constraint set by `expand_message_xmd`:
65+
// https://www.ietf.org/archive/id/draft-irtf-cfrg-hash-to-curve-13.html#section-5.4.1-4
66+
HashT::OutputSize: IsLessOrEqual<HashT::BlockSize>,
6167
{
6268
fn expand_message(msg: &[u8], dst: &'static [u8], len_in_bytes: usize) -> Result<Self> {
63-
if len_in_bytes > 0xFFFF {
69+
if len_in_bytes == 0 {
6470
return Err(Error);
6571
}
6672

67-
let b_in_bytes = HashT::OutputSize::to_usize();
68-
let ell = (len_in_bytes + b_in_bytes - 1) / b_in_bytes;
73+
let len_in_bytes_u16 = u16::try_from(len_in_bytes).map_err(|_| Error)?;
6974

70-
if ell > 255 {
71-
return Err(Error);
72-
}
75+
let b_in_bytes = HashT::OutputSize::to_usize();
76+
let ell = u8::try_from((len_in_bytes + b_in_bytes - 1) / b_in_bytes).map_err(|_| Error)?;
7377

7478
let domain = Domain::xmd::<HashT>(dst);
7579
let b_0 = HashT::new()
7680
.chain(GenericArray::<u8, HashT::BlockSize>::default())
7781
.chain(msg)
78-
.chain([(len_in_bytes >> 8) as u8, len_in_bytes as u8, 0u8])
82+
.chain(len_in_bytes_u16.to_be_bytes())
83+
.chain([0])
7984
.chain(domain.data())
80-
.chain([domain.len() as u8])
85+
.chain([domain.len()])
8186
.finalize();
8287

8388
let b_vals = HashT::new()
8489
.chain(&b_0[..])
8590
.chain([1u8])
8691
.chain(domain.data())
87-
.chain([domain.len() as u8])
92+
.chain([domain.len()])
8893
.finalize();
8994

9095
Ok(Self {

elliptic-curve/src/hash2field/expand_msg_xof.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::ExpandMsg;
2-
use crate::{hash2field::Domain, Result};
2+
use crate::{hash2field::Domain, Error, Result};
33
use digest::{ExtendableOutput, ExtendableOutputDirty, Update, XofReader};
44
use generic_array::typenum::U32;
55

@@ -17,12 +17,18 @@ where
1717
HashT: Default + ExtendableOutput + ExtendableOutputDirty + Update,
1818
{
1919
fn expand_message(msg: &[u8], dst: &'static [u8], len_in_bytes: usize) -> Result<Self> {
20+
if len_in_bytes == 0 {
21+
return Err(Error);
22+
}
23+
24+
let len_in_bytes = u16::try_from(len_in_bytes).map_err(|_| Error)?;
25+
2026
let domain = Domain::<U32>::xof::<HashT>(dst);
2127
let reader = HashT::default()
2228
.chain(msg)
23-
.chain([(len_in_bytes >> 8) as u8, len_in_bytes as u8])
29+
.chain(len_in_bytes.to_be_bytes())
2430
.chain(domain.data())
25-
.chain([domain.len() as u8])
31+
.chain([domain.len()])
2632
.finalize_xof();
2733
Ok(Self { reader })
2834
}

0 commit comments

Comments
 (0)