Skip to content

Commit 9ff8b0a

Browse files
committed
Account for identity point during conversion
1 parent 645c80e commit 9ff8b0a

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

ed448-goldilocks/src/montgomery/point.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,11 @@ impl ProjectiveMontgomeryPoint {
166166

167167
/// Convert the point to its form without the y-coordinate
168168
pub fn to_projective_x(&self) -> ProjectiveMontgomeryXpoint {
169-
ProjectiveMontgomeryXpoint::new(self.U, self.W)
169+
ProjectiveMontgomeryXpoint::conditional_select(
170+
&ProjectiveMontgomeryXpoint::new(self.U, self.W),
171+
&ProjectiveMontgomeryXpoint::IDENTITY,
172+
self.ct_eq(&Self::IDENTITY),
173+
)
170174
}
171175

172176
/// Convert the point to affine form without the y-coordinate
@@ -384,6 +388,22 @@ mod tests {
384388
assert_eq!(goldilocks_point.to_montgomery(), montgomery_res);
385389
}
386390

391+
#[test]
392+
fn test_montgomery_x() {
393+
let x_identity = ProjectiveMontgomeryXpoint::IDENTITY;
394+
let identity = ProjectiveMontgomeryPoint::IDENTITY;
395+
396+
assert_eq!(identity.to_projective_x(), x_identity);
397+
}
398+
399+
#[test]
400+
fn test_montgomery_affine_x() {
401+
let x_identity = ProjectiveMontgomeryXpoint::IDENTITY.to_affine();
402+
let identity = ProjectiveMontgomeryPoint::IDENTITY.to_affine();
403+
404+
assert_eq!(identity.to_affine_x(), x_identity);
405+
}
406+
387407
#[test]
388408
fn hash_with_test_vectors() {
389409
const DST: &[u8] = b"QUUX-V01-CS02-with-curve448_XOF:SHAKE256_ELL2_RO_";

ed448-goldilocks/src/montgomery/x.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const LOW_C: MontgomeryXpoint = MontgomeryXpoint([
4141
]);
4242

4343
/// A point in Montgomery form
44-
#[derive(Copy, Clone)]
44+
#[derive(Copy, Clone, Eq)]
4545
pub struct MontgomeryXpoint(pub [u8; 56]);
4646

4747
impl Default for MontgomeryXpoint {
@@ -69,10 +69,9 @@ impl PartialEq for MontgomeryXpoint {
6969
self.ct_eq(other).into()
7070
}
7171
}
72-
impl Eq for MontgomeryXpoint {}
7372

7473
/// A Projective point in Montgomery form
75-
#[derive(Copy, Clone, Debug)]
74+
#[derive(Copy, Clone, Debug, Eq)]
7675
pub struct ProjectiveMontgomeryXpoint {
7776
U: FieldElement,
7877
W: FieldElement,
@@ -143,6 +142,12 @@ impl MontgomeryXpoint {
143142
}
144143
}
145144

145+
impl ConstantTimeEq for ProjectiveMontgomeryXpoint {
146+
fn ct_eq(&self, other: &Self) -> Choice {
147+
self.U.ct_eq(&other.U) & self.W.ct_eq(&other.W)
148+
}
149+
}
150+
146151
impl ConditionallySelectable for ProjectiveMontgomeryXpoint {
147152
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
148153
Self {
@@ -152,6 +157,12 @@ impl ConditionallySelectable for ProjectiveMontgomeryXpoint {
152157
}
153158
}
154159

160+
impl PartialEq for ProjectiveMontgomeryXpoint {
161+
fn eq(&self, other: &Self) -> bool {
162+
self.ct_eq(other).into()
163+
}
164+
}
165+
155166
impl Mul<&MontgomeryScalar> for &ProjectiveMontgomeryXpoint {
156167
type Output = ProjectiveMontgomeryXpoint;
157168

@@ -341,14 +352,19 @@ impl ProjectiveMontgomeryXpoint {
341352

342353
/// Convert the point to its form including the y-coordinate
343354
pub fn to_extended(&self, sign: Choice) -> ProjectiveMontgomeryPoint {
344-
ProjectiveMontgomeryPoint::new(self.U, self.y(sign), self.W)
355+
ProjectiveMontgomeryPoint::conditional_select(
356+
&ProjectiveMontgomeryPoint::new(self.U, self.y(sign), self.W),
357+
&ProjectiveMontgomeryPoint::IDENTITY,
358+
self.ct_eq(&Self::IDENTITY),
359+
)
345360
}
346361
}
347362

348363
#[cfg(test)]
349364
mod tests {
350365
use super::*;
351366
use crate::EdwardsPoint;
367+
use elliptic_curve::CurveGroup;
352368
use hex_literal::hex;
353369
use sha3::Shake256;
354370

@@ -366,6 +382,22 @@ mod tests {
366382
assert_eq!(goldilocks_point.to_montgomery_x(), montgomery_res);
367383
}
368384

385+
#[test]
386+
fn test_montgomery_extended() {
387+
let x_identity = ProjectiveMontgomeryXpoint::IDENTITY;
388+
let identity = ProjectiveMontgomeryPoint::IDENTITY;
389+
390+
assert_eq!(x_identity.to_extended(Choice::from(1)), identity);
391+
}
392+
393+
#[test]
394+
fn test_montgomery_extended_affine() {
395+
let x_identity = ProjectiveMontgomeryXpoint::IDENTITY.to_affine();
396+
let identity = ProjectiveMontgomeryPoint::IDENTITY.to_affine();
397+
398+
assert_eq!(x_identity.to_extended(Choice::from(1)), identity);
399+
}
400+
369401
#[test]
370402
fn hash_with_test_vectors() {
371403
const DST: &[u8] = b"QUUX-V01-CS02-with-curve448_XOF:SHAKE256_ELL2_RO_";

0 commit comments

Comments
 (0)