Skip to content

Commit e7805ae

Browse files
committed
Use elliptic-curve with ff/group v0.14.0
Companion PR to RustCypto/traits#2431 which migrates everything to use the upstream releases of `ff`/`group` v0.14.0. To make this work, it's using a vendored copy of `wnaf.rs` in the `elliptic-curve` crate which has been modified to support big endian `PrimeField::Repr` as well as multiscalar multiplication.
1 parent 151c6b3 commit e7805ae

23 files changed

Lines changed: 250 additions & 199 deletions

File tree

Cargo.lock

Lines changed: 26 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,3 @@ primefield = { path = "primefield" }
2828
primeorder = { path = "primeorder" }
2929

3030
elliptic-curve = { git = "http://github.com/RustCrypto/traits.git" }
31-
rustcrypto-group = { git = "https://github.com/RustCrypto/group" }

ed448-goldilocks/src/decaf/affine.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
use crate::decaf::points::DecafPointRepr;
12
use crate::{
23
Decaf448FieldBytes, DecafPoint, DecafScalar, ORDER,
34
curve::twedwards::affine::AffinePoint as InnerAffinePoint, field::FieldElement,
45
};
56
use elliptic_curve::{
6-
Error, Generate, ctutils,
7-
ops::{Mul, MulVartime},
7+
CurveGroup, Error, Generate, ctutils,
8+
group::{CurveAffine, GroupEncoding},
9+
ops::{Mul, MulVartime, Neg},
810
point::{AffineCoordinates, NonIdentity},
911
zeroize::DefaultIsZeroes,
1012
};
@@ -102,6 +104,27 @@ impl AffineCoordinates for AffinePoint {
102104
}
103105
}
104106

107+
impl CurveAffine for AffinePoint {
108+
type Curve = DecafPoint;
109+
type Scalar = DecafScalar;
110+
111+
fn identity() -> AffinePoint {
112+
Self::IDENTITY
113+
}
114+
115+
fn generator() -> AffinePoint {
116+
DecafPoint::GENERATOR.to_affine()
117+
}
118+
119+
fn is_identity(&self) -> Choice {
120+
self.to_decaf().is_identity()
121+
}
122+
123+
fn to_curve(&self) -> DecafPoint {
124+
self.to_decaf()
125+
}
126+
}
127+
105128
impl DefaultIsZeroes for AffinePoint {}
106129

107130
impl Generate for AffinePoint {
@@ -110,6 +133,23 @@ impl Generate for AffinePoint {
110133
}
111134
}
112135

136+
impl GroupEncoding for AffinePoint {
137+
type Repr = DecafPointRepr;
138+
139+
fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
140+
DecafPoint::from_bytes(bytes).map(|point| point.to_affine())
141+
}
142+
143+
fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
144+
// No unchecked conversion possible for compressed points
145+
Self::from_bytes(bytes)
146+
}
147+
148+
fn to_bytes(&self) -> Self::Repr {
149+
self.to_decaf().to_bytes()
150+
}
151+
}
152+
113153
/// The constant-time alternative is available at [`NonIdentity::new()`].
114154
impl TryFrom<AffinePoint> for NonIdentity<AffinePoint> {
115155
type Error = Error;
@@ -157,3 +197,11 @@ impl MulVartime<&DecafScalar> for &AffinePoint {
157197
}
158198

159199
define_mul_variants!(LHS = AffinePoint, RHS = DecafScalar, Output = DecafPoint);
200+
201+
impl Neg for AffinePoint {
202+
type Output = AffinePoint;
203+
204+
fn neg(self) -> Self::Output {
205+
self.to_decaf().neg().to_affine()
206+
}
207+
}

ed448-goldilocks/src/decaf/points.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ impl Generate for DecafPoint {
266266
impl Group for DecafPoint {
267267
type Scalar = DecafScalar;
268268

269-
fn try_from_rng<R>(rng: &mut R) -> Result<Self, R::Error>
269+
fn try_random<R>(rng: &mut R) -> Result<Self, R::Error>
270270
where
271271
R: TryRng + ?Sized,
272272
{
@@ -341,9 +341,9 @@ impl<const N: usize> LinearCombination<[(DecafPoint, DecafScalar); N]> for Decaf
341341
impl LinearCombination<[(DecafPoint, DecafScalar)]> for DecafPoint {}
342342

343343
impl CurveGroup for DecafPoint {
344-
type AffineRepr = DecafAffinePoint;
344+
type Affine = DecafAffinePoint;
345345

346-
fn to_affine(&self) -> Self::AffineRepr {
346+
fn to_affine(&self) -> Self::Affine {
347347
DecafAffinePoint(self.0.to_extensible().to_affine())
348348
}
349349
}

ed448-goldilocks/src/edwards/affine.rs

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use crate::{field::FieldElement, *};
22
use core::fmt::{Display, Formatter, LowerHex, Result as FmtResult, UpperHex};
3+
use elliptic_curve::array::Array;
34
use elliptic_curve::{
45
Error, Generate, ctutils,
5-
ops::{Mul, MulVartime},
6-
point::NonIdentity,
6+
group::{CurveAffine, Group, GroupEncoding},
7+
ops::{Mul, MulVartime, Neg},
8+
point::{AffineCoordinates, NonIdentity},
79
zeroize::DefaultIsZeroes,
810
};
911
use rand_core::{TryCryptoRng, TryRng};
@@ -105,7 +107,7 @@ impl AffinePoint {
105107
///
106108
/// Helper method that has `TryRng` bounds so `ProjectivePoint` can call it for its `group`
107109
/// impls, otherwise end users should use the `Generate` trait.
108-
pub(crate) fn try_from_rng<R>(rng: &mut R) -> Result<Self, R::Error>
110+
pub(crate) fn try_random<R>(rng: &mut R) -> Result<Self, R::Error>
109111
where
110112
R: TryRng + ?Sized,
111113
{
@@ -120,6 +122,56 @@ impl AffinePoint {
120122
}
121123
}
122124

125+
impl AffineCoordinates for AffinePoint {
126+
type FieldRepr = Ed448FieldBytes;
127+
128+
fn from_coordinates(x: &Self::FieldRepr, y: &Self::FieldRepr) -> CtOption<Self> {
129+
let point = Self {
130+
x: FieldElement::from_bytes_extended(&x.0),
131+
y: FieldElement::from_bytes_extended(&y.0),
132+
};
133+
134+
CtOption::new(point, point.is_on_curve())
135+
}
136+
137+
fn x(&self) -> Self::FieldRepr {
138+
Ed448FieldBytes::from(self.x.to_bytes_extended())
139+
}
140+
141+
fn y(&self) -> Self::FieldRepr {
142+
Ed448FieldBytes::from(self.y.to_bytes_extended())
143+
}
144+
145+
fn x_is_odd(&self) -> Choice {
146+
self.x.is_negative()
147+
}
148+
149+
fn y_is_odd(&self) -> Choice {
150+
self.y.is_negative()
151+
}
152+
}
153+
154+
impl CurveAffine for AffinePoint {
155+
type Curve = EdwardsPoint;
156+
type Scalar = EdwardsScalar;
157+
158+
fn identity() -> AffinePoint {
159+
Self::IDENTITY
160+
}
161+
162+
fn generator() -> AffinePoint {
163+
EdwardsPoint::GENERATOR.to_affine()
164+
}
165+
166+
fn is_identity(&self) -> Choice {
167+
self.to_edwards().is_identity()
168+
}
169+
170+
fn to_curve(&self) -> EdwardsPoint {
171+
self.into()
172+
}
173+
}
174+
123175
impl Default for AffinePoint {
124176
fn default() -> Self {
125177
Self::IDENTITY
@@ -156,6 +208,8 @@ impl ctutils::CtSelect for AffinePoint {
156208
}
157209
}
158210

211+
impl DefaultIsZeroes for AffinePoint {}
212+
159213
impl Eq for AffinePoint {}
160214
impl PartialEq for AffinePoint {
161215
fn eq(&self, other: &Self) -> bool {
@@ -165,41 +219,27 @@ impl PartialEq for AffinePoint {
165219

166220
impl Generate for AffinePoint {
167221
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
168-
Self::try_from_rng(rng)
222+
Self::try_random(rng)
169223
}
170224
}
171225

172-
impl elliptic_curve::point::AffineCoordinates for AffinePoint {
173-
type FieldRepr = Ed448FieldBytes;
226+
impl GroupEncoding for AffinePoint {
227+
type Repr = Array<u8, U57>;
174228

175-
fn from_coordinates(x: &Self::FieldRepr, y: &Self::FieldRepr) -> CtOption<Self> {
176-
let point = Self {
177-
x: FieldElement::from_bytes_extended(&x.0),
178-
y: FieldElement::from_bytes_extended(&y.0),
179-
};
180-
181-
CtOption::new(point, point.is_on_curve())
229+
fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
230+
CompressedEdwardsY((*bytes).into()).decompress()
182231
}
183232

184-
fn x(&self) -> Self::FieldRepr {
185-
Ed448FieldBytes::from(self.x.to_bytes_extended())
233+
fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
234+
// No unchecked conversion possible for compressed points
235+
Self::from_bytes(bytes)
186236
}
187237

188-
fn y(&self) -> Self::FieldRepr {
189-
Ed448FieldBytes::from(self.y.to_bytes_extended())
190-
}
191-
192-
fn x_is_odd(&self) -> Choice {
193-
self.x.is_negative()
194-
}
195-
196-
fn y_is_odd(&self) -> Choice {
197-
self.y.is_negative()
238+
fn to_bytes(&self) -> Self::Repr {
239+
self.compress().0.into()
198240
}
199241
}
200242

201-
impl DefaultIsZeroes for AffinePoint {}
202-
203243
impl From<NonIdentity<AffinePoint>> for AffinePoint {
204244
fn from(affine: NonIdentity<AffinePoint>) -> Self {
205245
affine.to_point()
@@ -251,6 +291,14 @@ define_mul_variants!(
251291
Output = EdwardsPoint
252292
);
253293

294+
impl Neg for AffinePoint {
295+
type Output = AffinePoint;
296+
297+
fn neg(self) -> Self::Output {
298+
self.to_edwards().neg().to_affine()
299+
}
300+
}
301+
254302
/// The compressed internal representation of a point on the Twisted Edwards Curve
255303
pub type PointBytes = [u8; 57];
256304

0 commit comments

Comments
 (0)