Skip to content

Commit de32cb5

Browse files
committed
Move MontgomeryXpoint to its own module
1 parent 4b9eb55 commit de32cb5

File tree

2 files changed

+226
-223
lines changed

2 files changed

+226
-223
lines changed

ed448-goldilocks/src/montgomery.rs

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

0 commit comments

Comments
 (0)