Skip to content

Commit db0cf62

Browse files
committed
Add configurable mapping function
1 parent 4d82666 commit db0cf62

File tree

20 files changed

+192
-153
lines changed

20 files changed

+192
-153
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ed448-goldilocks/src/decaf/points.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -599,8 +599,6 @@ impl From<NonIdentity<DecafPoint>> for DecafPoint {
599599
mod test {
600600
use super::*;
601601
use crate::TWISTED_EDWARDS_BASE_POINT;
602-
use hash2curve::ExpandMsgXof;
603-
use sha3::Shake256;
604602

605603
#[test]
606604
fn test_edwards_decaf_operations() {
@@ -751,11 +749,7 @@ mod test {
751749
#[test]
752750
fn test_hash_to_curve() {
753751
let msg = b"Hello, world!";
754-
let point = hash2curve::hash_from_bytes::<Decaf448, ExpandMsgXof<Shake256>>(
755-
&[msg],
756-
&[b"test_hash_to_curve"],
757-
)
758-
.unwrap();
752+
let point = Decaf448::hash_from_bytes(msg, b"test_hash_to_curve").unwrap();
759753
assert_eq!(point.0.is_on_curve().unwrap_u8(), 1u8);
760754
assert_ne!(point, DecafPoint::IDENTITY);
761755
assert_ne!(point, DecafPoint::GENERATOR);

ed448-goldilocks/src/edwards/extended.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -947,9 +947,7 @@ mod tests {
947947
];
948948

949949
for (msg, x, y) in MSGS {
950-
let p =
951-
hash2curve::hash_from_bytes::<Ed448, ExpandMsgXof<sha3::Shake256>>(&[msg], &[DST])
952-
.unwrap();
950+
let p = Ed448::hash_from_bytes(msg, DST).unwrap();
953951
assert_eq!(p.is_on_curve().unwrap_u8(), 1u8);
954952
let p = p.to_affine();
955953
let mut xx = [0u8; 56];
@@ -986,11 +984,7 @@ mod tests {
986984
];
987985

988986
for (msg, x, y) in MSGS {
989-
let p = hash2curve::encode_from_bytes::<Ed448, ExpandMsgXof<sha3::Shake256>>(
990-
&[msg],
991-
&[DST],
992-
)
993-
.unwrap();
987+
let p = Ed448::encode_from_bytes(msg, DST).unwrap();
994988
assert_eq!(p.is_on_curve().unwrap_u8(), 1u8);
995989
let p = p.to_affine();
996990
let mut xx = [0u8; 56];

ed448-goldilocks/src/field.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod element;
22
mod scalar;
33

44
pub(crate) use element::*;
5+
pub use element::{Decaf448Map, Elligator2};
56
pub(crate) use scalar::CurveWithScalar;
67
pub use scalar::{MODULUS_LIMBS, ORDER, Scalar, ScalarBytes, WIDE_ORDER, WideScalarBytes};
78

ed448-goldilocks/src/field/element.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use elliptic_curve::{
1313
array::Array,
1414
bigint::{
1515
Integer, NonZero, U448, U704, Zero,
16-
consts::{U28, U56, U84, U88},
16+
consts::{U56, U84, U88},
1717
modular::ConstMontyParams,
1818
},
1919
zeroize::DefaultIsZeroes,
@@ -190,21 +190,21 @@ impl Neg for FieldElement {
190190
}
191191
}
192192

193-
impl MapToCurve for Ed448 {
194-
type SecurityLevel = U28;
195-
type FieldElement = FieldElement;
196-
type Length = U84;
193+
/// Elligator2 mapping for [`Ed448`] hash-to-curve operations.
194+
#[derive(Clone, Copy, Debug)]
195+
pub struct Elligator2;
197196

197+
impl MapToCurve<Ed448> for Elligator2 {
198198
fn map_to_curve(element: FieldElement) -> EdwardsPoint {
199199
element.map_to_curve_elligator2().isogeny().to_edwards()
200200
}
201201
}
202202

203-
impl MapToCurve for Decaf448 {
204-
type SecurityLevel = U28;
205-
type FieldElement = FieldElement;
206-
type Length = U56;
203+
/// [`Decaf448`] mapping for hash-to-curve operations.
204+
#[derive(Clone, Copy, Debug)]
205+
pub struct Decaf448Map;
207206

207+
impl MapToCurve<Decaf448> for Decaf448Map {
208208
fn map_to_curve(element: FieldElement) -> DecafPoint {
209209
DecafPoint(element.map_to_curve_decaf448())
210210
}

ed448-goldilocks/src/lib.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub(crate) mod montgomery;
4747
#[cfg(feature = "signing")]
4848
pub(crate) mod sign;
4949

50-
pub(crate) use field::{GOLDILOCKS_BASE_POINT, TWISTED_EDWARDS_BASE_POINT};
50+
pub(crate) use field::{FieldElement, GOLDILOCKS_BASE_POINT, TWISTED_EDWARDS_BASE_POINT};
5151

5252
pub use decaf::{
5353
AffinePoint as DecafAffinePoint, CompressedDecaf, DecafPoint, DecafScalar, DecafScalarBytes,
@@ -57,18 +57,18 @@ pub use edwards::{
5757
AffinePoint, CompressedEdwardsY, EdwardsPoint, EdwardsScalar, EdwardsScalarBytes,
5858
WideEdwardsScalarBytes,
5959
};
60-
pub use field::{MODULUS_LIMBS, ORDER, Scalar, WIDE_ORDER};
60+
pub use field::{Decaf448Map, Elligator2, MODULUS_LIMBS, ORDER, Scalar, WIDE_ORDER};
6161
pub use montgomery::{MontgomeryPoint, ProjectiveMontgomeryPoint};
6262
#[cfg(feature = "signing")]
6363
pub use sign::*;
6464

6565
use elliptic_curve::{
6666
Curve, FieldBytesEncoding, PrimeCurve,
67-
array::typenum::{U56, U57},
67+
array::typenum::{U28, U56, U57, U84},
6868
bigint::{ArrayEncoding, Odd, U448},
6969
point::PointCompression,
7070
};
71-
use hash2curve::{ExpandMsgXof, GroupDigest};
71+
use hash2curve::{ExpandMsgXof, GroupDigest, HashToCurve};
7272
use sha3::Shake256;
7373

7474
/// Edwards448 curve.
@@ -116,11 +116,18 @@ impl elliptic_curve::CurveArithmetic for Ed448 {
116116
type Scalar = EdwardsScalar;
117117
}
118118

119+
impl HashToCurve for Ed448 {
120+
type SecurityLevel = U28;
121+
type FieldElement = FieldElement;
122+
type Length = U84;
123+
}
124+
119125
impl GroupDigest for Ed448 {
120126
const HASH_TO_CURVE_ID: &[u8] = b"edwards448_XOF:SHAKE256_ELL2_RO_";
121127
const ENCODE_TO_CURVE_ID: &[u8] = b"edwards448_XOF:SHAKE256_ELL2_NU_";
122128

123129
type ExpandMsg = ExpandMsgXof<Shake256>;
130+
type MapToCurve = Elligator2;
124131
}
125132

126133
/// Decaf448 curve.
@@ -168,9 +175,16 @@ impl elliptic_curve::CurveArithmetic for Decaf448 {
168175
type Scalar = DecafScalar;
169176
}
170177

178+
impl HashToCurve for Decaf448 {
179+
type SecurityLevel = U28;
180+
type FieldElement = FieldElement;
181+
type Length = U56;
182+
}
183+
171184
impl GroupDigest for Decaf448 {
172185
const HASH_TO_CURVE_ID: &[u8] = b"decaf448_XOF:SHAKE256_D448MAP_RO_";
173186
const ENCODE_TO_CURVE_ID: &[u8] = b"decaf448_XOF:SHAKE256_D448MAP_NU_";
174187

175188
type ExpandMsg = ExpandMsgXof<Shake256>;
189+
type MapToCurve = Decaf448Map;
176190
}

hash2curve/src/group_digest.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
//! Traits for handling hash to curve.
22
3-
use crate::{ExpandMsg, MapToCurve};
3+
use crate::{ExpandMsg, HashToCurve, MapToCurve};
44
use elliptic_curve::ProjectivePoint;
55

66
/// Hash arbitrary byte sequences to a valid group element.
7-
pub trait GroupDigest: MapToCurve {
7+
pub trait GroupDigest: HashToCurve {
88
/// Suite ID for the [hash to curve routine](Self::hash_from_bytes).
99
const HASH_TO_CURVE_ID: &[u8];
1010
/// Suite ID for the [encode to curve routine](Self::encode_from_bytes).
1111
const ENCODE_TO_CURVE_ID: &[u8];
1212

1313
/// The `expand_message` function to use.
1414
type ExpandMsg: ExpandMsg<Self::SecurityLevel>;
15+
/// The mapping function.
16+
type MapToCurve: MapToCurve<Self>;
1517

1618
/// Computes the hash to curve routine.
1719
///
@@ -36,7 +38,7 @@ pub trait GroupDigest: MapToCurve {
3638
dst: &[u8],
3739
) -> Result<ProjectivePoint<Self>, <Self::ExpandMsg as ExpandMsg<Self::SecurityLevel>>::Error>
3840
{
39-
crate::hash_from_bytes::<Self, Self::ExpandMsg>(&[msg], &[dst])
41+
crate::hash_from_bytes::<Self, Self::ExpandMsg, Self::MapToCurve>(&[msg], &[dst])
4042
}
4143

4244
/// Computes the encode to curve routine.
@@ -61,6 +63,6 @@ pub trait GroupDigest: MapToCurve {
6163
dst: &[u8],
6264
) -> Result<ProjectivePoint<Self>, <Self::ExpandMsg as ExpandMsg<Self::SecurityLevel>>::Error>
6365
{
64-
crate::encode_from_bytes::<Self, Self::ExpandMsg>(&[msg], &[dst])
66+
crate::encode_from_bytes::<Self, Self::ExpandMsg, Self::MapToCurve>(&[msg], &[dst])
6567
}
6668
}

hash2curve/src/lib.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ mod group_digest;
2626
mod hash2field;
2727
mod map2curve;
2828
mod oprf;
29+
mod parameters;
2930

3031
pub use group_digest::*;
3132
pub use hash2field::*;
3233
pub use map2curve::*;
3334
pub use oprf::*;
35+
pub use parameters::*;
3436

3537
use elliptic_curve::ProjectivePoint;
3638
use elliptic_curve::array::typenum::NonZero;
@@ -51,14 +53,18 @@ use elliptic_curve::ops::Reduce;
5153
///
5254
/// [`ExpandMsgXmdError`]: crate::ExpandMsgXmdError
5355
/// [`ExpandMsgXofError`]: crate::ExpandMsgXofError
54-
pub fn hash_from_bytes<C, X>(msg: &[&[u8]], dst: &[&[u8]]) -> Result<ProjectivePoint<C>, X::Error>
56+
pub fn hash_from_bytes<C, X, M>(
57+
msg: &[&[u8]],
58+
dst: &[&[u8]],
59+
) -> Result<ProjectivePoint<C>, X::Error>
5560
where
56-
C: MapToCurve,
61+
C: HashToCurve,
5762
X: ExpandMsg<C::SecurityLevel>,
63+
M: MapToCurve<C>,
5864
{
5965
let [u0, u1] = hash_to_field::<2, X, _, C::FieldElement, C::Length>(msg, dst)?;
60-
let q0 = C::map_to_curve(u0);
61-
let q1 = C::map_to_curve(u1);
66+
let q0 = M::map_to_curve(u0);
67+
let q1 = M::map_to_curve(u1);
6268
Ok((q0 + q1).clear_cofactor())
6369
}
6470

@@ -74,13 +80,17 @@ where
7480
///
7581
/// [`ExpandMsgXmdError`]: crate::ExpandMsgXmdError
7682
/// [`ExpandMsgXofError`]: crate::ExpandMsgXofError
77-
pub fn encode_from_bytes<C, X>(msg: &[&[u8]], dst: &[&[u8]]) -> Result<ProjectivePoint<C>, X::Error>
83+
pub fn encode_from_bytes<C, X, M>(
84+
msg: &[&[u8]],
85+
dst: &[&[u8]],
86+
) -> Result<ProjectivePoint<C>, X::Error>
7887
where
79-
C: MapToCurve,
88+
C: HashToCurve,
8089
X: ExpandMsg<C::SecurityLevel>,
90+
M: MapToCurve<C>,
8191
{
8292
let [u] = hash_to_field::<1, X, _, C::FieldElement, C::Length>(msg, dst)?;
83-
let q0 = C::map_to_curve(u);
93+
let q0 = M::map_to_curve(u);
8494
Ok(q0.clear_cofactor())
8595
}
8696

@@ -100,7 +110,7 @@ where
100110
/// [`ExpandMsgXofError`]: crate::ExpandMsgXofError
101111
pub fn hash_to_scalar<C, X, L>(msg: &[&[u8]], dst: &[&[u8]]) -> Result<C::Scalar, X::Error>
102112
where
103-
C: MapToCurve,
113+
C: HashToCurve,
104114
X: ExpandMsg<C::SecurityLevel>,
105115
L: ArraySize + NonZero,
106116
C::Scalar: Reduce<Array<u8, L>>,

hash2curve/src/map2curve.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,12 @@
11
//! Traits for mapping field elements to points on the curve.
22
3-
use elliptic_curve::array::typenum::{NonZero, Unsigned};
4-
use elliptic_curve::array::{Array, ArraySize};
5-
use elliptic_curve::group::cofactor::CofactorGroup;
6-
use elliptic_curve::ops::Reduce;
7-
use elliptic_curve::{CurveArithmetic, ProjectivePoint};
3+
use elliptic_curve::ProjectivePoint;
4+
5+
use crate::HashToCurve;
86

97
/// Trait for converting field elements into a point via a mapping method like
108
/// Simplified Shallue-van de Woestijne-Ulas or Elligator.
11-
pub trait MapToCurve:
12-
CurveArithmetic<ProjectivePoint: CofactorGroup<Subgroup = Self::ProjectivePoint>>
13-
{
14-
/// The target security level in bytes:
15-
/// <https://www.rfc-editor.org/rfc/rfc9380.html#section-8.9-2.2>
16-
/// <https://www.rfc-editor.org/rfc/rfc9380.html#name-target-security-levels>
17-
type SecurityLevel: Unsigned;
18-
/// The field element representation for a group value with multiple elements.
19-
type FieldElement: Reduce<Array<u8, Self::Length>> + Default + Copy;
20-
/// The `L` parameter as specified in the [RFC](https://www.rfc-editor.org/rfc/rfc9380.html#section-5-6).
21-
type Length: ArraySize + NonZero;
22-
9+
pub trait MapToCurve<C: HashToCurve> {
2310
/// Map a field element into a curve point.
24-
fn map_to_curve(element: Self::FieldElement) -> ProjectivePoint<Self>;
11+
fn map_to_curve(element: C::FieldElement) -> ProjectivePoint<C>;
2512
}

hash2curve/src/parameters.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use elliptic_curve::CurveArithmetic;
2+
use elliptic_curve::array::typenum::{NonZero, Unsigned};
3+
use elliptic_curve::array::{Array, ArraySize};
4+
use elliptic_curve::group::cofactor::CofactorGroup;
5+
use elliptic_curve::ops::Reduce;
6+
7+
/// Trait defining curve parameters for hash-to-curve operations.
8+
pub trait HashToCurve:
9+
CurveArithmetic<ProjectivePoint: CofactorGroup<Subgroup = Self::ProjectivePoint>>
10+
{
11+
/// The target security level in bytes:
12+
/// <https://www.rfc-editor.org/rfc/rfc9380.html#section-8.9-2.2>
13+
/// <https://www.rfc-editor.org/rfc/rfc9380.html#name-target-security-levels>
14+
type SecurityLevel: Unsigned;
15+
/// The field element representation for a group value with multiple elements.
16+
type FieldElement: Reduce<Array<u8, Self::Length>> + Default + Copy;
17+
/// The `L` parameter as specified in the [RFC](https://www.rfc-editor.org/rfc/rfc9380.html#section-5-6).
18+
type Length: ArraySize + NonZero;
19+
}

0 commit comments

Comments
 (0)