Skip to content

Commit b7410d1

Browse files
committed
Move MontgomeryXpoint to its own module
1 parent a988df0 commit b7410d1

File tree

2 files changed

+230
-227
lines changed

2 files changed

+230
-227
lines changed

ed448-goldilocks/src/montgomery.rs

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

1111
#![allow(non_snake_case)]
1212

13-
// use crate::constants::A_PLUS_TWO_OVER_FOUR;
14-
use crate::EdwardsScalar;
15-
use crate::edwards::extended::EdwardsPoint;
16-
use crate::field::FieldElement;
17-
use core::fmt;
18-
use core::ops::Mul;
19-
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
13+
mod x;
2014

21-
impl MontgomeryXpoint {
22-
/// First low order point on Curve448 and it's twist
23-
pub const LOW_A: MontgomeryXpoint = MontgomeryXpoint([
24-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28-
]);
29-
/// Second low order point on Curve448 and it's twist
30-
pub const LOW_B: MontgomeryXpoint = MontgomeryXpoint([
31-
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35-
]);
36-
/// Third low order point on Curve448 and it's twist
37-
pub const LOW_C: MontgomeryXpoint = MontgomeryXpoint([
38-
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39-
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff,
40-
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
41-
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42-
]);
43-
}
44-
45-
/// A point in Montgomery form
46-
#[derive(Copy, Clone)]
47-
pub struct MontgomeryXpoint(pub [u8; 56]);
48-
49-
impl Default for MontgomeryXpoint {
50-
fn default() -> MontgomeryXpoint {
51-
Self([0u8; 56])
52-
}
53-
}
54-
55-
impl elliptic_curve::zeroize::DefaultIsZeroes for MontgomeryXpoint {}
56-
57-
impl fmt::Debug for MontgomeryXpoint {
58-
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
59-
self.0[..].fmt(formatter)
60-
}
61-
}
62-
63-
impl ConstantTimeEq for MontgomeryXpoint {
64-
fn ct_eq(&self, other: &MontgomeryXpoint) -> Choice {
65-
self.0.ct_eq(&other.0)
66-
}
67-
}
68-
69-
impl PartialEq for MontgomeryXpoint {
70-
fn eq(&self, other: &MontgomeryXpoint) -> bool {
71-
self.ct_eq(other).into()
72-
}
73-
}
74-
impl Eq for MontgomeryXpoint {}
75-
76-
/// A Projective point in Montgomery form
77-
#[derive(Copy, Clone, Debug)]
78-
pub struct ProjectiveMontgomeryXpoint {
79-
U: FieldElement,
80-
W: FieldElement,
81-
}
82-
83-
impl Mul<&EdwardsScalar> for &MontgomeryXpoint {
84-
type Output = MontgomeryXpoint;
85-
86-
#[allow(clippy::suspicious_arithmetic_impl)]
87-
fn mul(self, scalar: &EdwardsScalar) -> MontgomeryXpoint {
88-
// Algorithm 8 of Costello-Smith 2017
89-
let affine_u = FieldElement::from_bytes(&self.0);
90-
let mut x0 = ProjectiveMontgomeryXpoint::identity();
91-
let mut x1 = ProjectiveMontgomeryXpoint {
92-
U: affine_u,
93-
W: FieldElement::ONE,
94-
};
95-
96-
let bits = scalar.bits();
97-
let mut swap = 0;
98-
for s in (0..448).rev() {
99-
let bit = bits[s] as u8;
100-
let choice: u8 = swap ^ bit;
101-
102-
ProjectiveMontgomeryXpoint::conditional_swap(&mut x0, &mut x1, Choice::from(choice));
103-
differential_add_and_double(&mut x0, &mut x1, &affine_u);
104-
105-
swap = bit;
106-
}
107-
108-
x0.to_affine()
109-
}
110-
}
111-
112-
impl Mul<&MontgomeryXpoint> for &EdwardsScalar {
113-
type Output = MontgomeryXpoint;
114-
115-
fn mul(self, point: &MontgomeryXpoint) -> MontgomeryXpoint {
116-
point * self
117-
}
118-
}
119-
120-
impl MontgomeryXpoint {
121-
/// Returns the generator specified in RFC7748
122-
pub const GENERATOR: Self = Self([
123-
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127-
]);
128-
129-
/// Convert this point to an [`EdwardsPoint`]
130-
pub fn to_edwards(&self, _sign: u8) -> Option<EdwardsPoint> {
131-
// We use the 4-isogeny to map to the Ed448.
132-
// This is different to Curve25519, where we use a birational map.
133-
todo!()
134-
}
135-
136-
/// Returns true if the point is one of the low order points
137-
pub fn is_low_order(&self) -> bool {
138-
(*self == Self::LOW_A) || (*self == Self::LOW_B) || (*self == Self::LOW_C)
139-
}
140-
141-
/// View the point as a byte slice
142-
pub fn as_bytes(&self) -> &[u8; 56] {
143-
&self.0
144-
}
145-
146-
/// Convert the point to a ProjectiveMontgomeryPoint
147-
pub fn to_projective(&self) -> ProjectiveMontgomeryXpoint {
148-
ProjectiveMontgomeryXpoint {
149-
U: FieldElement::from_bytes(&self.0),
150-
W: FieldElement::ONE,
151-
}
152-
}
153-
}
154-
155-
impl ConditionallySelectable for ProjectiveMontgomeryXpoint {
156-
fn conditional_select(
157-
a: &ProjectiveMontgomeryXpoint,
158-
b: &ProjectiveMontgomeryXpoint,
159-
choice: Choice,
160-
) -> ProjectiveMontgomeryXpoint {
161-
ProjectiveMontgomeryXpoint {
162-
U: FieldElement::conditional_select(&a.U, &b.U, choice),
163-
W: FieldElement::conditional_select(&a.W, &b.W, choice),
164-
}
165-
}
166-
}
167-
168-
fn differential_add_and_double(
169-
P: &mut ProjectiveMontgomeryXpoint,
170-
Q: &mut ProjectiveMontgomeryXpoint,
171-
affine_PmQ: &FieldElement,
172-
) {
173-
let t0 = P.U + P.W;
174-
let t1 = P.U - P.W;
175-
let t2 = Q.U + Q.W;
176-
let t3 = Q.U - Q.W;
177-
178-
let t4 = t0.square(); // (U_P + W_P)^2 = U_P^2 + 2 U_P W_P + W_P^2
179-
let t5 = t1.square(); // (U_P - W_P)^2 = U_P^2 - 2 U_P W_P + W_P^2
180-
181-
let t6 = t4 - t5; // 4 U_P W_P
182-
183-
let t7 = t0 * t3; // (U_P + W_P) (U_Q - W_Q) = U_P U_Q + W_P U_Q - U_P W_Q - W_P W_Q
184-
let t8 = t1 * t2; // (U_P - W_P) (U_Q + W_Q) = U_P U_Q - W_P U_Q + U_P W_Q - W_P W_Q
185-
186-
let t9 = t7 + t8; // 2 (U_P U_Q - W_P W_Q)
187-
let t10 = t7 - t8; // 2 (W_P U_Q - U_P W_Q)
188-
189-
let t11 = t9.square(); // 4 (U_P U_Q - W_P W_Q)^2
190-
let t12 = t10.square(); // 4 (W_P U_Q - U_P W_Q)^2
191-
let t13 = FieldElement::A_PLUS_TWO_OVER_FOUR * t6; // (A + 2) U_P U_Q
192-
193-
let t14 = t4 * t5; // ((U_P + W_P)(U_P - W_P))^2 = (U_P^2 - W_P^2)^2
194-
let t15 = t13 + t5; // (U_P - W_P)^2 + (A + 2) U_P W_P
195-
196-
let t16 = t6 * t15; // 4 (U_P W_P) ((U_P - W_P)^2 + (A + 2) U_P W_P)
197-
let t17 = *affine_PmQ * t12; // U_D * 4 (W_P U_Q - U_P W_Q)^2
198-
let t18 = t11; // W_D * 4 (U_P U_Q - W_P W_Q)^2
199-
200-
P.U = t14; // U_{P'} = (U_P + W_P)^2 (U_P - W_P)^2
201-
P.W = t16; // W_{P'} = (4 U_P W_P) ((U_P - W_P)^2 + ((A + 2)/4) 4 U_P W_P)
202-
Q.U = t18; // U_{Q'} = W_D * 4 (U_P U_Q - W_P W_Q)^2
203-
Q.W = t17; // W_{Q'} = U_D * 4 (W_P U_Q - U_P W_Q)^2
204-
}
205-
206-
impl ProjectiveMontgomeryXpoint {
207-
/// The identity element of the group: the point at infinity.
208-
pub fn identity() -> ProjectiveMontgomeryXpoint {
209-
ProjectiveMontgomeryXpoint {
210-
U: FieldElement::ONE,
211-
W: FieldElement::ZERO,
212-
}
213-
}
214-
215-
/// Convert the point to affine form
216-
pub fn to_affine(&self) -> MontgomeryXpoint {
217-
let x = self.U * self.W.invert();
218-
MontgomeryXpoint(x.to_bytes())
219-
}
220-
}
221-
222-
#[cfg(test)]
223-
mod tests {
224-
225-
use super::*;
226-
227-
#[test]
228-
fn test_montgomery_edwards() {
229-
let scalar = EdwardsScalar::from(200u32);
230-
use crate::GOLDILOCKS_BASE_POINT as bp;
231-
232-
// Montgomery scalar mul
233-
let montgomery_bp = bp.to_montgomery_x();
234-
let montgomery_res = &montgomery_bp * &scalar;
235-
236-
// Goldilocks scalar mul
237-
let goldilocks_point = bp.scalar_mul(&scalar);
238-
assert_eq!(goldilocks_point.to_montgomery_x(), montgomery_res);
239-
}
240-
}
15+
pub use x::{MontgomeryXpoint, ProjectiveMontgomeryXpoint};

0 commit comments

Comments
 (0)