Skip to content

Commit 12eef9c

Browse files
authored
Implement AffineCoordinates::from_coordinates (#1405)
Implementation of RustCrypto/traits#1996 Addresses RustCrypto/traits#1994
1 parent 037249d commit 12eef9c

8 files changed

Lines changed: 62 additions & 31 deletions

File tree

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ opt-level = 2
2323

2424
[patch.crates-io]
2525
ed448-goldilocks = { path = "ed448-goldilocks" }
26+
# https://github.com/RustCrypto/traits/pull/1996
27+
elliptic-curve = { git = "https://github.com/RustCrypto/traits" }
2628
hash2curve = { path = "hash2curve" }
2729
primefield = { path = "primefield" }
2830
primeorder = { path = "primeorder" }

ed448-goldilocks/src/curve/twedwards/affine.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![allow(dead_code)]
22
use crate::curve::twedwards::{extended::ExtendedPoint, extensible::ExtensiblePoint};
33
use crate::field::FieldElement;
4-
use subtle::{Choice, ConditionallySelectable};
4+
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
55

66
/// This point representation is not a part of the API.
77
///
@@ -31,11 +31,11 @@ impl AffinePoint {
3131
};
3232

3333
/// Checks if the AffinePoint is on the TwistedEdwards curve
34-
fn is_on_curve(&self) -> bool {
34+
pub(crate) fn is_on_curve(&self) -> Choice {
3535
let xx = self.x.square();
3636
let yy = self.y.square();
3737

38-
yy - xx == FieldElement::ONE + (FieldElement::TWISTED_D * xx * yy)
38+
(yy - xx).ct_eq(&(FieldElement::ONE + (FieldElement::TWISTED_D * xx * yy)))
3939
}
4040

4141
// Negates an AffinePoint
@@ -142,7 +142,7 @@ mod tests {
142142
fn test_negation() {
143143
use crate::TWISTED_EDWARDS_BASE_POINT;
144144
let a = TWISTED_EDWARDS_BASE_POINT.to_extensible().to_affine();
145-
assert!(a.is_on_curve());
145+
assert_eq!(a.is_on_curve().unwrap_u8(), 1);
146146

147147
let neg_a = a.negate();
148148
let got = neg_a.add(&a);

ed448-goldilocks/src/decaf/affine.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::curve::twedwards::affine::AffinePoint as InnerAffinePoint;
22
use crate::field::FieldElement;
3-
use crate::{Decaf448FieldBytes, DecafPoint, DecafScalar};
3+
use crate::{Decaf448FieldBytes, DecafPoint, DecafScalar, ORDER};
44
use core::ops::Mul;
55
use elliptic_curve::{
66
Error,
77
point::{AffineCoordinates, NonIdentity},
88
zeroize::DefaultIsZeroes,
99
};
10-
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
10+
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
1111

1212
/// Affine point on the twisted curve
1313
#[derive(Copy, Clone, Debug, Default)]
@@ -39,6 +39,18 @@ impl Eq for AffinePoint {}
3939
impl AffineCoordinates for AffinePoint {
4040
type FieldRepr = Decaf448FieldBytes;
4141

42+
fn from_coordinates(x: &Self::FieldRepr, y: &Self::FieldRepr) -> CtOption<Self> {
43+
let point = Self(InnerAffinePoint {
44+
x: FieldElement::from_bytes(&x.0),
45+
y: FieldElement::from_bytes(&y.0),
46+
});
47+
48+
CtOption::new(
49+
point,
50+
point.0.is_on_curve() & (point * DecafScalar::new(*ORDER)).ct_eq(&DecafPoint::IDENTITY),
51+
)
52+
}
53+
4254
fn x(&self) -> Self::FieldRepr {
4355
Decaf448FieldBytes::from(self.x())
4456
}

ed448-goldilocks/src/edwards/affine.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ impl Eq for AffinePoint {}
4545
impl elliptic_curve::point::AffineCoordinates for AffinePoint {
4646
type FieldRepr = Ed448FieldBytes;
4747

48+
fn from_coordinates(x: &Self::FieldRepr, y: &Self::FieldRepr) -> CtOption<Self> {
49+
let point = Self {
50+
x: FieldElement::from_bytes_extended(&x.0),
51+
y: FieldElement::from_bytes_extended(&y.0),
52+
};
53+
54+
CtOption::new(point, point.is_on_curve())
55+
}
56+
4857
fn x(&self) -> Self::FieldRepr {
4958
Ed448FieldBytes::from(self.x.to_bytes_extended())
5059
}

ed448-goldilocks/src/field/element.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,10 @@ impl FieldElement {
363363
Self(ConstMontyType::new(&U448::from_le_slice(bytes)))
364364
}
365365

366+
pub fn from_bytes_extended(bytes: &[u8; 57]) -> Self {
367+
Self(ConstMontyType::new(&U448::from_le_slice(&bytes[..56])))
368+
}
369+
366370
pub fn from_repr(bytes: &[u8; 56]) -> CtOption<Self> {
367371
let integer = U448::from_le_slice(bytes);
368372
let is_some = integer.ct_lt(MODULUS::PARAMS.modulus());

k256/src/arithmetic/affine.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,21 @@ impl PrimeCurveAffine for AffinePoint {
127127
impl AffineCoordinates for AffinePoint {
128128
type FieldRepr = FieldBytes;
129129

130+
fn from_coordinates(x: &Self::FieldRepr, y: &Self::FieldRepr) -> CtOption<Self> {
131+
let x = FieldElement::from_bytes(x);
132+
let y = FieldElement::from_bytes(y);
133+
134+
x.and_then(|x| {
135+
y.and_then(|y| {
136+
// Check that the point is on the curve
137+
let lhs = (y * &y).negate(1);
138+
let rhs = x * &x * &x + &CURVE_EQUATION_B;
139+
let point = Self::new(x, y);
140+
CtOption::new(point, (lhs + &rhs).normalizes_to_zero())
141+
})
142+
})
143+
}
144+
130145
fn x(&self) -> FieldBytes {
131146
self.x.to_bytes()
132147
}
@@ -276,20 +291,7 @@ impl FromEncodedPoint<Secp256k1> for AffinePoint {
276291
sec1::Coordinates::Compressed { x, y_is_odd } => {
277292
AffinePoint::decompress(x, Choice::from(y_is_odd as u8))
278293
}
279-
sec1::Coordinates::Uncompressed { x, y } => {
280-
let x = FieldElement::from_bytes(x);
281-
let y = FieldElement::from_bytes(y);
282-
283-
x.and_then(|x| {
284-
y.and_then(|y| {
285-
// Check that the point is on the curve
286-
let lhs = (y * &y).negate(1);
287-
let rhs = x * &x * &x + &CURVE_EQUATION_B;
288-
let point = Self::new(x, y);
289-
CtOption::new(point, (lhs + &rhs).normalizes_to_zero())
290-
})
291-
})
292-
}
294+
sec1::Coordinates::Uncompressed { x, y } => Self::from_coordinates(x, y),
293295
}
294296
}
295297
}

primeorder/src/affine.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,20 @@ where
103103
impl<C> AffineCoordinates for AffinePoint<C>
104104
where
105105
C: PrimeCurveParams,
106+
FieldBytes<C>: Copy,
106107
{
107108
type FieldRepr = FieldBytes<C>;
108109

110+
fn from_coordinates(x: &Self::FieldRepr, y: &Self::FieldRepr) -> CtOption<Self> {
111+
C::FieldElement::from_repr(*y).and_then(|y| {
112+
C::FieldElement::from_repr(*x).and_then(|x| {
113+
let lhs = y * &y;
114+
let rhs = x * &x * &x + &(C::EQUATION_A * &x) + &C::EQUATION_B;
115+
CtOption::new(Self { x, y, infinity: 0 }, lhs.ct_eq(&rhs))
116+
})
117+
})
118+
}
119+
109120
fn x(&self) -> FieldBytes<C> {
110121
self.x.to_repr()
111122
}
@@ -212,15 +223,7 @@ where
212223
sec1::Coordinates::Compressed { x, y_is_odd } => {
213224
Self::decompress(x, Choice::from(y_is_odd as u8))
214225
}
215-
sec1::Coordinates::Uncompressed { x, y } => {
216-
C::FieldElement::from_repr(*y).and_then(|y| {
217-
C::FieldElement::from_repr(*x).and_then(|x| {
218-
let lhs = y * &y;
219-
let rhs = x * &x * &x + &(C::EQUATION_A * &x) + &C::EQUATION_B;
220-
CtOption::new(Self { x, y, infinity: 0 }, lhs.ct_eq(&rhs))
221-
})
222-
})
223-
}
226+
sec1::Coordinates::Uncompressed { x, y } => Self::from_coordinates(x, y),
224227
}
225228
}
226229
}

0 commit comments

Comments
 (0)