Skip to content

Commit f7ac90c

Browse files
committed
Add full-coordinate MontgomeryPoint skeleton
1 parent 5c8ea4e commit f7ac90c

File tree

4 files changed

+229
-3
lines changed

4 files changed

+229
-3
lines changed

ed448-goldilocks/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ pub use edwards::{
6161
WideEdwardsScalarBytes,
6262
};
6363
pub use field::{MODULUS_LIMBS, ORDER, Scalar, WIDE_ORDER};
64-
pub use montgomery::{MontgomeryXpoint, ProjectiveMontgomeryXpoint};
64+
pub use montgomery::{
65+
MontgomeryPoint, MontgomeryXpoint, ProjectiveMontgomeryPoint, ProjectiveMontgomeryXpoint,
66+
};
6567
pub use ristretto::{CompressedRistretto, RistrettoPoint};
6668
#[cfg(feature = "signing")]
6769
pub use sign::*;
@@ -171,3 +173,7 @@ impl elliptic_curve::CurveArithmetic for Decaf448 {
171173
impl GroupDigest for Decaf448 {
172174
type K = U28;
173175
}
176+
177+
/// Curve448 curve.
178+
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
179+
pub struct Curve448;

ed448-goldilocks/src/montgomery.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#![allow(non_snake_case)]
1212

13+
mod point;
1314
mod x;
1415

16+
pub use point::{MontgomeryPoint, ProjectiveMontgomeryPoint};
1517
pub use x::{MontgomeryXpoint, ProjectiveMontgomeryXpoint};
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
use elliptic_curve::bigint::U448;
2+
use subtle::Choice;
3+
use subtle::ConditionallySelectable;
4+
use subtle::ConstantTimeEq;
5+
6+
use super::{MontgomeryXpoint, ProjectiveMontgomeryXpoint};
7+
use crate::field::ConstMontyType;
8+
use crate::field::FieldElement;
9+
10+
/// A point in Montgomery form including the y-coordinate.
11+
#[derive(Copy, Clone, Debug, Default)]
12+
pub struct MontgomeryPoint {
13+
pub(super) x: FieldElement,
14+
pub(super) y: FieldElement,
15+
}
16+
17+
impl MontgomeryPoint {
18+
/// The identity element of the group: the point at infinity.
19+
pub const IDENTITY: Self = Self {
20+
x: FieldElement::ZERO,
21+
y: FieldElement::ONE,
22+
};
23+
24+
pub(crate) fn new(x: FieldElement, y: FieldElement) -> Self {
25+
Self { x, y }
26+
}
27+
28+
/// Convert the point to its form without the y-coordinate
29+
pub fn to_affine_x(&self) -> MontgomeryXpoint {
30+
MontgomeryXpoint(self.x.to_bytes())
31+
}
32+
}
33+
34+
impl ConditionallySelectable for MontgomeryPoint {
35+
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
36+
Self {
37+
x: FieldElement::conditional_select(&a.x, &b.x, choice),
38+
y: FieldElement::conditional_select(&a.y, &b.y, choice),
39+
}
40+
}
41+
}
42+
43+
impl ConstantTimeEq for MontgomeryPoint {
44+
fn ct_eq(&self, other: &Self) -> Choice {
45+
self.x.ct_eq(&other.x) & self.y.ct_eq(&other.y)
46+
}
47+
}
48+
49+
impl PartialEq for MontgomeryPoint {
50+
fn eq(&self, other: &Self) -> bool {
51+
self.ct_eq(other).into()
52+
}
53+
}
54+
impl Eq for MontgomeryPoint {}
55+
56+
impl From<ProjectiveMontgomeryPoint> for MontgomeryPoint {
57+
fn from(value: ProjectiveMontgomeryPoint) -> Self {
58+
value.to_affine()
59+
}
60+
}
61+
62+
/// A Projective point in Montgomery form including the y-coordinate.
63+
#[derive(Copy, Clone, Debug, Eq)]
64+
pub struct ProjectiveMontgomeryPoint {
65+
pub(super) U: FieldElement,
66+
pub(super) V: FieldElement,
67+
pub(super) W: FieldElement,
68+
}
69+
70+
impl ProjectiveMontgomeryPoint {
71+
/// The identity element of the group: the point at infinity.
72+
pub const IDENTITY: Self = Self {
73+
U: FieldElement::ZERO,
74+
V: FieldElement::ONE,
75+
W: FieldElement::ZERO,
76+
};
77+
78+
/// The generator point
79+
pub const GENERATOR: Self = Self {
80+
U: FieldElement(ConstMontyType::new(&U448::from_u64(5))),
81+
V: FieldElement(ConstMontyType::new(&U448::from_be_hex(
82+
"7d235d1295f5b1f66c98ab6e58326fcecbae5d34f55545d060f75dc28df3f6edb8027e2346430d211312c4b150677af76fd7223d457b5b1a",
83+
))),
84+
W: FieldElement::ONE,
85+
};
86+
87+
pub(crate) fn new(U: FieldElement, V: FieldElement, W: FieldElement) -> Self {
88+
Self { U, V, W }
89+
}
90+
91+
/// Convert the point to its form without the y-coordinate
92+
pub fn to_projective_x(&self) -> ProjectiveMontgomeryXpoint {
93+
ProjectiveMontgomeryXpoint::conditional_select(
94+
&ProjectiveMontgomeryXpoint {
95+
U: self.U,
96+
W: self.W,
97+
},
98+
&ProjectiveMontgomeryXpoint::IDENTITY,
99+
self.ct_eq(&Self::IDENTITY),
100+
)
101+
}
102+
103+
/// Convert the point to affine form without the y-coordinate
104+
pub fn to_affine_x(&self) -> MontgomeryXpoint {
105+
self.to_projective_x().to_affine()
106+
}
107+
108+
/// Convert the point to affine form
109+
pub fn to_affine(&self) -> MontgomeryPoint {
110+
let W_inv = self.W.invert();
111+
let x = self.U * W_inv;
112+
let y = self.V * W_inv;
113+
114+
MontgomeryPoint { x, y }
115+
}
116+
}
117+
118+
impl ConditionallySelectable for ProjectiveMontgomeryPoint {
119+
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
120+
Self {
121+
U: FieldElement::conditional_select(&a.U, &b.U, choice),
122+
V: FieldElement::conditional_select(&a.V, &b.V, choice),
123+
W: FieldElement::conditional_select(&a.W, &b.W, choice),
124+
}
125+
}
126+
}
127+
128+
impl ConstantTimeEq for ProjectiveMontgomeryPoint {
129+
fn ct_eq(&self, other: &Self) -> Choice {
130+
self.U.ct_eq(&other.U) & self.V.ct_eq(&other.V) & self.W.ct_eq(&other.W)
131+
}
132+
}
133+
134+
impl Default for ProjectiveMontgomeryPoint {
135+
fn default() -> Self {
136+
Self::IDENTITY
137+
}
138+
}
139+
impl PartialEq for ProjectiveMontgomeryPoint {
140+
fn eq(&self, other: &Self) -> bool {
141+
self.ct_eq(other).into()
142+
}
143+
}
144+
145+
impl From<MontgomeryPoint> for ProjectiveMontgomeryPoint {
146+
fn from(value: MontgomeryPoint) -> Self {
147+
ProjectiveMontgomeryPoint {
148+
U: value.x,
149+
V: value.y,
150+
W: FieldElement::ONE,
151+
}
152+
}
153+
}
154+
155+
#[cfg(test)]
156+
mod tests {
157+
use super::*;
158+
159+
#[test]
160+
fn to_projective_x() {
161+
let x_identity = ProjectiveMontgomeryXpoint::IDENTITY;
162+
let identity = ProjectiveMontgomeryPoint::IDENTITY;
163+
164+
assert_eq!(identity.to_projective_x(), x_identity);
165+
}
166+
167+
#[test]
168+
fn to_affine_x() {
169+
let x_identity = ProjectiveMontgomeryXpoint::IDENTITY.to_affine();
170+
let identity = ProjectiveMontgomeryPoint::IDENTITY.to_affine_x();
171+
172+
assert_eq!(identity, x_identity);
173+
}
174+
}

ed448-goldilocks/src/montgomery/x.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// use crate::constants::A_PLUS_TWO_OVER_FOUR;
2+
use super::{MontgomeryPoint, ProjectiveMontgomeryPoint};
23
use crate::EdwardsScalar;
34
use crate::edwards::extended::EdwardsPoint;
45
use crate::field::ConstMontyType;
@@ -62,8 +63,8 @@ impl Eq for MontgomeryXpoint {}
6263
/// A Projective point in Montgomery form
6364
#[derive(Copy, Clone, Debug, Eq)]
6465
pub struct ProjectiveMontgomeryXpoint {
65-
U: FieldElement,
66-
W: FieldElement,
66+
pub(super) U: FieldElement,
67+
pub(super) W: FieldElement,
6768
}
6869

6970
impl Mul<&EdwardsScalar> for &MontgomeryXpoint {
@@ -145,6 +146,16 @@ impl MontgomeryXpoint {
145146
W: FieldElement::ONE,
146147
}
147148
}
149+
150+
/// Convert the point to projective form including the y-coordinate
151+
pub fn to_extended_projective(&self, sign: Choice) -> ProjectiveMontgomeryPoint {
152+
self.to_projective().to_extended(sign)
153+
}
154+
155+
/// Convert the point to its form including the y-coordinate
156+
pub fn to_extended(&self, sign: Choice) -> MontgomeryPoint {
157+
self.to_projective().to_extended_affine(sign)
158+
}
148159
}
149160

150161
impl ConstantTimeEq for ProjectiveMontgomeryXpoint {
@@ -272,6 +283,23 @@ impl ProjectiveMontgomeryXpoint {
272283
let x = self.U * self.W.invert();
273284
MontgomeryXpoint(x.to_bytes())
274285
}
286+
287+
/// Convert the point to affine form including the y-coordinate
288+
pub fn to_extended_affine(&self, sign: Choice) -> MontgomeryPoint {
289+
let x = self.U * self.W.invert();
290+
let y = self.y(sign);
291+
292+
MontgomeryPoint::new(x, y)
293+
}
294+
295+
/// Convert the point to its form including the y-coordinate
296+
pub fn to_extended(&self, sign: Choice) -> ProjectiveMontgomeryPoint {
297+
ProjectiveMontgomeryPoint::conditional_select(
298+
&ProjectiveMontgomeryPoint::new(self.U, self.y(sign), self.W),
299+
&ProjectiveMontgomeryPoint::IDENTITY,
300+
self.ct_eq(&Self::IDENTITY),
301+
)
302+
}
275303
}
276304

277305
#[cfg(test)]
@@ -293,4 +321,20 @@ mod tests {
293321
montgomery_res.to_affine()
294322
);
295323
}
324+
325+
#[test]
326+
fn to_extended() {
327+
let x_identity = ProjectiveMontgomeryXpoint::IDENTITY;
328+
let identity = ProjectiveMontgomeryPoint::IDENTITY;
329+
330+
assert_eq!(x_identity.to_extended(Choice::from(1)), identity);
331+
}
332+
333+
#[test]
334+
fn to_extended_affine() {
335+
let x_identity = ProjectiveMontgomeryXpoint::IDENTITY.to_affine();
336+
let identity = ProjectiveMontgomeryPoint::IDENTITY.to_affine();
337+
338+
assert_eq!(x_identity.to_extended(Choice::from(1)), identity);
339+
}
296340
}

0 commit comments

Comments
 (0)