Skip to content

Commit 4de33de

Browse files
elliptic-curve: update MapToCurve to avoid CofactorGroup dependency (#1866)
Fixes #1146 This update implements `MapToCurve` for the curve itself rather than for the field element, and removes the dependency on `CofactorGroup`. Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
1 parent 857f6de commit 4de33de

File tree

2 files changed

+38
-34
lines changed

2 files changed

+38
-34
lines changed

elliptic-curve/src/hash2curve/group_digest.rs

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
//! Traits for handling hash to curve.
22
33
use super::{ExpandMsg, FromOkm, MapToCurve, hash_to_field};
4-
use crate::{CurveArithmetic, ProjectivePoint, Result};
5-
use group::cofactor::CofactorGroup;
4+
use crate::{ProjectivePoint, Result};
65
use hybrid_array::typenum::Unsigned;
76

8-
/// Adds hashing arbitrary byte sequences to a valid group element
9-
pub trait GroupDigest: CurveArithmetic
10-
where
11-
ProjectivePoint<Self>: CofactorGroup,
12-
{
13-
/// The field element representation for a group value with multiple elements
14-
type FieldElement: FromOkm + MapToCurve<Output = ProjectivePoint<Self>> + Default + Copy;
15-
7+
/// Hash arbitrary byte sequences to a valid group element.
8+
pub trait GroupDigest: MapToCurve {
169
/// The target security level in bytes:
1710
/// <https://www.rfc-editor.org/rfc/rfc9380.html#section-8.9-2.2>
1811
/// <https://www.rfc-editor.org/rfc/rfc9380.html#name-target-security-levels>
@@ -58,19 +51,9 @@ where
5851
) -> Result<ProjectivePoint<Self>> {
5952
let mut u = [Self::FieldElement::default(), Self::FieldElement::default()];
6053
hash_to_field::<X, _>(msgs, dsts, &mut u)?;
61-
let q0 = u[0].map_to_curve();
62-
let q1 = u[1].map_to_curve();
63-
// Ideally we could add and then clear cofactor once
64-
// thus saving a call but the field elements may not
65-
// add properly due to the underlying implementation
66-
// which could result in an incorrect subgroup.
67-
// This is caused curve coefficients being different than
68-
// what is usually implemented.
69-
// FieldElement expects the `a` and `b` to be the original values
70-
// isogenies are different with curves like k256 and bls12-381.
71-
// This problem doesn't manifest for curves with no isogeny like p256.
72-
// For k256 and p256 clear_cofactor doesn't do anything anyway so it will be a no-op.
73-
Ok(q0.clear_cofactor().into() + q1.clear_cofactor())
54+
let q0 = Self::map_to_curve(u[0]);
55+
let q1 = Self::map_to_curve(u[1]);
56+
Ok(Self::add_and_map_to_subgroup(q0, q1))
7457
}
7558

7659
/// Computes the encode to curve routine.
@@ -98,8 +81,8 @@ where
9881
) -> Result<ProjectivePoint<Self>> {
9982
let mut u = [Self::FieldElement::default()];
10083
hash_to_field::<X, _>(msgs, dsts, &mut u)?;
101-
let q0 = u[0].map_to_curve();
102-
Ok(q0.clear_cofactor().into())
84+
let q0 = Self::map_to_curve(u[0]);
85+
Ok(Self::map_to_subgroup(q0))
10386
}
10487

10588
/// Computes the hash to field routine according to
Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
11
//! Traits for mapping field elements to points on the curve.
22
3-
/// Trait for converting field elements into a point
4-
/// via a mapping method like Simplified Shallue-van de Woestijne-Ulas
5-
/// or Elligator
6-
pub trait MapToCurve {
7-
/// The output point
8-
type Output;
9-
10-
/// Map a field element into a point
11-
fn map_to_curve(&self) -> Self::Output;
3+
use crate::{CurveArithmetic, ProjectivePoint};
4+
5+
use super::FromOkm;
6+
7+
/// Trait for converting field elements into a point via a mapping method like
8+
/// Simplified Shallue-van de Woestijne-Ulas or Elligator.
9+
pub trait MapToCurve: CurveArithmetic {
10+
/// The intermediate representation, an element of the curve which may or may not
11+
/// be in the curve subgroup.
12+
type CurvePoint;
13+
/// The field element representation for a group value with multiple elements.
14+
type FieldElement: FromOkm + Default + Copy;
15+
16+
/// Map a field element into a curve point.
17+
fn map_to_curve(element: Self::FieldElement) -> Self::CurvePoint;
18+
19+
/// Map a curve point to a point in the curve subgroup.
20+
/// This is usually done by clearing the cofactor, if necessary.
21+
fn map_to_subgroup(point: Self::CurvePoint) -> ProjectivePoint<Self>;
22+
23+
/// Combine two curve points into a point in the curve subgroup.
24+
/// This is usually done by clearing the cofactor of the sum. In case
25+
/// addition is not implemented for `Self::CurvePoint`, then both terms
26+
/// must be mapped to the subgroup individually before being added.
27+
fn add_and_map_to_subgroup(
28+
lhs: Self::CurvePoint,
29+
rhs: Self::CurvePoint,
30+
) -> ProjectivePoint<Self> {
31+
Self::map_to_subgroup(lhs) + Self::map_to_subgroup(rhs)
32+
}
1233
}

0 commit comments

Comments
 (0)