Skip to content

Commit 60ba440

Browse files
committed
Reduce unnecessary conversions to ExtensiblePoint and back
1 parent b9a0167 commit 60ba440

File tree

11 files changed

+209
-195
lines changed

11 files changed

+209
-195
lines changed

ed448-goldilocks/src/curve/scalar_mul/double_and_add.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use crate::curve::twedwards::extended::ExtendedPoint;
2+
use crate::curve::twedwards::extensible::ExtensiblePoint;
23
use subtle::{Choice, ConditionallySelectable};
34

45
/// Traditional double and add algorithm
5-
pub(crate) fn double_and_add(point: &ExtendedPoint, s_bits: [bool; 448]) -> ExtendedPoint {
6-
let mut result = ExtendedPoint::IDENTITY;
6+
pub(crate) fn double_and_add(point: &ExtendedPoint, s_bits: [bool; 448]) -> ExtensiblePoint {
7+
let mut result = ExtensiblePoint::IDENTITY;
78

89
// NB, we reverse here, so we are going from MSB to LSB
910
// XXX: Would be great if subtle had a From<u32> for Choice. But maybe that is not it's purpose?
@@ -12,7 +13,7 @@ pub(crate) fn double_and_add(point: &ExtendedPoint, s_bits: [bool; 448]) -> Exte
1213

1314
let mut p = ExtendedPoint::IDENTITY;
1415
p.conditional_assign(point, Choice::from(bit as u8));
15-
result = result.add(&p);
16+
result = result.to_extended().add_extended(&p);
1617
}
1718

1819
result

ed448-goldilocks/src/curve/scalar_mul/variable_base.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::EdwardsScalar;
55
use crate::curve::twedwards::{extended::ExtendedPoint, extensible::ExtensiblePoint};
66
use subtle::{Choice, ConditionallyNegatable};
77

8-
pub fn variable_base(point: &ExtendedPoint, s: &EdwardsScalar) -> ExtendedPoint {
8+
pub fn variable_base(point: &ExtendedPoint, s: &EdwardsScalar) -> ExtensiblePoint {
99
let mut result = ExtensiblePoint::IDENTITY;
1010

1111
// Recode Scalar
@@ -28,10 +28,10 @@ pub fn variable_base(point: &ExtendedPoint, s: &EdwardsScalar) -> ExtendedPoint
2828
let mut neg_P = lookup.select(abs_value);
2929
neg_P.conditional_negate(Choice::from((sign) as u8));
3030

31-
result = result.add_projective_niels(&neg_P);
31+
result = result.to_extended().add_projective_niels(&neg_P);
3232
}
3333

34-
result.to_extended()
34+
result
3535
}
3636

3737
#[cfg(test)]
@@ -57,7 +57,7 @@ mod test {
5757
// Lets see if this is conserved over the isogenies
5858
let edwards_point = twisted_point.to_untwisted();
5959
let got_untwisted_point = edwards_point.scalar_mul(&scalar);
60-
let expected_untwisted_point = got.to_untwisted();
60+
let expected_untwisted_point = got.to_extended().to_untwisted();
6161
assert_eq!(got_untwisted_point, expected_untwisted_point);
6262
}
6363

@@ -69,9 +69,8 @@ mod test {
6969
let exp = variable_base(&x, &EdwardsScalar::from(1u8));
7070
assert!(x == exp);
7171
// Test that 2 * (P + P) = 4 * P
72-
let x_ext = x.to_extensible();
73-
let expected_two_x = x_ext.add_extensible(&x_ext).double();
72+
let expected_two_x = x.add_extended(&x).double();
7473
let got = variable_base(&x, &EdwardsScalar::from(4u8));
75-
assert!(expected_two_x.to_extended() == got);
74+
assert!(expected_two_x == got);
7675
}
7776
}

ed448-goldilocks/src/curve/scalar_mul/window/wnaf.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ pub struct LookupTable([ProjectiveNielsPoint; 8]);
66

77
/// Precomputes odd multiples of the point passed in
88
impl From<&ExtendedPoint> for LookupTable {
9-
fn from(point: &ExtendedPoint) -> LookupTable {
10-
let P = point.to_extensible();
11-
9+
fn from(P: &ExtendedPoint) -> LookupTable {
1210
let mut table = [P.to_projective_niels(); 8];
1311

1412
for i in 1..8 {
15-
table[i] = P.add_projective_niels(&table[i - 1]).to_projective_niels();
13+
table[i] = P
14+
.add_projective_niels(&table[i - 1])
15+
.to_extended()
16+
.to_projective_niels();
1617
}
1718

1819
LookupTable(table)
@@ -42,11 +43,8 @@ fn test_lookup() {
4243
let mut expected_point = ExtendedPoint::IDENTITY;
4344
for i in 0..8 {
4445
let selected_point = points.select(i);
45-
assert_eq!(selected_point.to_extended(), expected_point);
46+
assert_eq!(selected_point.to_extensible(), expected_point);
4647

47-
expected_point = expected_point
48-
.to_extensible()
49-
.add_extended(&p)
50-
.to_extended();
48+
expected_point = expected_point.add_extended(&p).to_extended();
5149
}
5250
}

ed448-goldilocks/src/curve/twedwards.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,21 @@ use crate::field::FieldElement;
1212
pub(crate) struct IsogenyMap {
1313
pub(crate) X: FieldElement,
1414
pub(crate) Y: FieldElement,
15+
pub(crate) Z: FieldElement,
1516
pub(crate) T: FieldElement,
17+
}
18+
19+
pub(crate) struct IsogenyMapResult {
20+
pub(crate) X: FieldElement,
21+
pub(crate) Y: FieldElement,
1622
pub(crate) Z: FieldElement,
23+
pub(crate) T1: FieldElement,
24+
pub(crate) T2: FieldElement,
1725
}
1826

1927
impl IsogenyMap {
2028
// (1.) https://eprint.iacr.org/2014/027.pdf
21-
pub(crate) fn map(&self, scale: impl FnOnce(FieldElement) -> FieldElement) -> Self {
29+
pub(crate) fn map(&self, scale: impl FnOnce(FieldElement) -> FieldElement) -> IsogenyMapResult {
2230
// x = 2xy / (y^2 - a*x^2)
2331
// y = (y^2 + a*x^2) / (2 - y^2 - a*x^2)
2432

@@ -53,9 +61,10 @@ impl IsogenyMap {
5361

5462
let X = x_numerator * y_denom;
5563
let Y = y_numerator * x_denom;
56-
let T = x_numerator * y_numerator;
5764
let Z = x_denom * y_denom;
65+
let T1 = x_numerator;
66+
let T2 = y_numerator;
5867

59-
Self { X, Y, T, Z }
68+
IsogenyMapResult { X, Y, Z, T1, T2 }
6069
}
6170
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,14 @@ impl AffineNielsPoint {
121121
&& (self.td == other.td)
122122
}
123123

124-
/// Converts an AffineNielsPoint to an ExtendedPoint
125-
pub(crate) fn to_extended(self) -> ExtendedPoint {
126-
ExtendedPoint {
124+
/// Converts an AffineNielsPoint to an ExtensiblePoint
125+
pub(crate) fn to_extensible(self) -> ExtensiblePoint {
126+
ExtensiblePoint {
127127
X: self.y_plus_x - self.y_minus_x,
128128
Y: self.y_minus_x + self.y_plus_x,
129129
Z: FieldElement::ONE,
130-
T: self.y_plus_x * self.y_minus_x,
130+
T1: self.y_plus_x,
131+
T2: self.y_minus_x,
131132
}
132133
}
133134
}
@@ -140,7 +141,7 @@ mod tests {
140141
#[test]
141142
fn test_negation() {
142143
use crate::TWISTED_EDWARDS_BASE_POINT;
143-
let a = TWISTED_EDWARDS_BASE_POINT.to_affine();
144+
let a = TWISTED_EDWARDS_BASE_POINT.to_extensible().to_affine();
144145
assert!(a.is_on_curve());
145146

146147
let neg_a = a.negate();

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

Lines changed: 119 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
#![allow(dead_code)]
33

44
use super::IsogenyMap;
5-
use super::affine::AffinePoint;
65
use super::extensible::ExtensiblePoint;
6+
use super::projective::ProjectiveNielsPoint;
7+
use super::{IsogenyMapResult, affine::AffineNielsPoint};
78
use crate::edwards::EdwardsPoint as EdwardsExtendedPoint;
89
use crate::field::FieldElement;
910
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
@@ -44,6 +45,11 @@ impl PartialEq for ExtendedPoint {
4445
self.ct_eq(other).into()
4546
}
4647
}
48+
impl PartialEq<ExtensiblePoint> for ExtendedPoint {
49+
fn eq(&self, other: &ExtensiblePoint) -> bool {
50+
self.to_extensible().ct_eq(other).into()
51+
}
52+
}
4753
impl Eq for ExtendedPoint {}
4854

4955
impl Default for ExtendedPoint {
@@ -70,14 +76,90 @@ impl ExtendedPoint {
7076
T: FieldElement::ZERO,
7177
};
7278

73-
/// Doubles an extended point
74-
pub(crate) fn double(&self) -> ExtendedPoint {
75-
self.to_extensible().double().to_extended()
79+
/// Adds an extensible point to an extended point
80+
/// Returns an extensible point
81+
/// (3.1) https://iacr.org/archive/asiacrypt2008/53500329/53500329.pdf
82+
pub fn add_extended(&self, other: &ExtendedPoint) -> ExtensiblePoint {
83+
let A = self.X * other.X;
84+
let B = self.Y * other.Y;
85+
let C = self.T * other.T * FieldElement::TWISTED_D;
86+
let D = self.Z * other.Z;
87+
let E = (self.X + self.Y) * (other.X + other.Y) - A - B;
88+
let F = D - C;
89+
let G = D + C;
90+
let H = B + A;
91+
ExtensiblePoint {
92+
X: E * F,
93+
Y: G * H,
94+
T1: E,
95+
T2: H,
96+
Z: F * G,
97+
}
7698
}
7799

78-
/// Adds an extended point to itself
79-
pub(crate) fn add(&self, other: &ExtendedPoint) -> ExtendedPoint {
80-
self.to_extensible().add_extended(other).to_extended()
100+
/// Subtracts an extensible point from an extended point
101+
/// Returns an extensible point
102+
/// This is a direct modification of the addition formula to the negation of `other`
103+
pub fn sub_extended(&self, other: &ExtendedPoint) -> ExtensiblePoint {
104+
let A = self.X * other.X;
105+
let B = self.Y * other.Y;
106+
let C = self.T * other.T * FieldElement::TWISTED_D;
107+
let D = self.Z * other.Z;
108+
let E = (self.X + self.Y) * (other.Y - other.X) + A - B;
109+
let F = D + C;
110+
let G = D - C;
111+
let H = B - A;
112+
ExtensiblePoint {
113+
X: E * F,
114+
Y: G * H,
115+
T1: E,
116+
T2: H,
117+
Z: F * G,
118+
}
119+
}
120+
121+
/// Adds an extensible point to an AffineNiels point
122+
/// Returns an Extensible point
123+
pub fn add_affine_niels(&self, other: AffineNielsPoint) -> ExtensiblePoint {
124+
let A = other.y_minus_x * (self.Y - self.X);
125+
let B = other.y_plus_x * (self.X + self.Y);
126+
let C = other.td * self.T;
127+
let D = B + A;
128+
let E = B - A;
129+
let F = self.Z - C;
130+
let G = self.Z + C;
131+
ExtensiblePoint {
132+
X: E * F,
133+
Y: G * D,
134+
Z: F * G,
135+
T1: E,
136+
T2: D,
137+
}
138+
}
139+
140+
/// Adds an extensible point to a ProjectiveNiels point
141+
/// Returns an extensible point
142+
/// (3.1)[Last set of formulas] https://iacr.org/archive/asiacrypt2008/53500329/53500329.pdf
143+
/// This differs from the formula above by a factor of 2. Saving 1 Double
144+
/// Cost 8M
145+
pub fn add_projective_niels(&self, other: &ProjectiveNielsPoint) -> ExtensiblePoint {
146+
// This is the only step which makes it different than adding an AffineNielsPoint
147+
let Z = self.Z * other.Z;
148+
149+
let A = (self.Y - self.X) * other.Y_minus_X;
150+
let B = (self.Y + self.X) * other.Y_plus_X;
151+
let C = other.Td * self.T;
152+
let D = B + A;
153+
let E = B - A;
154+
let F = Z - C;
155+
let G = Z + C;
156+
ExtensiblePoint {
157+
X: E * F,
158+
Y: G * D,
159+
Z: F * G,
160+
T1: E,
161+
T2: D,
162+
}
81163
}
82164

83165
/// Converts an ExtendedPoint to an ExtensiblePoint
@@ -91,31 +173,32 @@ impl ExtendedPoint {
91173
}
92174
}
93175

94-
/// Converts an extended point to Affine co-ordinates
95-
pub(crate) fn to_affine(self) -> AffinePoint {
96-
// Points to consider:
97-
// - All points where Z=0, translate to (0,0)
98-
// - The identity point has z=1, so it is not a problem
99-
100-
let INV_Z = self.Z.invert();
101-
102-
let x = self.X * INV_Z;
103-
let y = self.Y * INV_Z;
104-
105-
AffinePoint { x, y }
106-
}
107-
108176
/// Uses a 2-isogeny to map the point to the Ed448-Goldilocks
109177
pub fn to_untwisted(self) -> EdwardsExtendedPoint {
110-
let IsogenyMap { X, Y, T, Z } = IsogenyMap {
178+
let IsogenyMapResult { X, Y, Z, T1, T2 } = IsogenyMap {
111179
X: self.X,
112180
Y: self.Y,
113-
T: self.T,
114181
Z: self.Z,
182+
T: self.T,
115183
}
116184
.map(|f| -f);
117185

118-
EdwardsExtendedPoint { X, Y, Z, T }
186+
EdwardsExtendedPoint {
187+
X,
188+
Y,
189+
Z,
190+
T: T1 * T2,
191+
}
192+
}
193+
194+
/// Converts an Extensible point to a ProjectiveNiels Point
195+
pub fn to_projective_niels(self) -> ProjectiveNielsPoint {
196+
ProjectiveNielsPoint {
197+
Y_plus_X: self.X + self.Y,
198+
Y_minus_X: self.Y - self.X,
199+
Z: self.Z.double(),
200+
Td: self.T * FieldElement::TWO_TIMES_TWISTED_D,
201+
}
119202
}
120203

121204
/// Checks if the point is on the curve
@@ -159,6 +242,7 @@ impl ExtendedPoint {
159242
#[cfg(test)]
160243
mod tests {
161244
use super::*;
245+
use crate::curve::twedwards::affine::AffinePoint;
162246
use crate::{GOLDILOCKS_BASE_POINT, TWISTED_EDWARDS_BASE_POINT};
163247

164248
fn hex_to_field(hex: &'static str) -> FieldElement {
@@ -177,8 +261,8 @@ mod tests {
177261
let y = hex_to_field(
178262
"ae05e9634ad7048db359d6205086c2b0036ed7a035884dd7b7e36d728ad8c4b80d6565833a2a3098bbbcb2bed1cda06bdaeafbcdea9386ed",
179263
);
180-
let a = AffinePoint { x, y }.to_extended();
181-
let twist_a = a.to_untwisted().to_twisted();
264+
let a = AffinePoint { x, y }.to_extensible();
265+
let twist_a = a.to_extended().to_untwisted().to_twisted();
182266
assert_eq!(twist_a, a.double().double())
183267
}
184268

@@ -201,28 +285,28 @@ mod tests {
201285
#[test]
202286
fn test_point_add() {
203287
let a = TWISTED_EDWARDS_BASE_POINT;
204-
let b = a.double();
288+
let b = a.to_extensible().double().to_extended();
205289

206290
// A + B = B + A = C
207-
let c_1 = a.to_extensible().add_extended(&b).to_extended();
208-
let c_2 = b.to_extensible().add_extended(&a).to_extended();
291+
let c_1 = a.add_extended(&b).to_extended();
292+
let c_2 = b.add_extended(&a).to_extended();
209293
assert!(c_1 == c_2);
210294

211295
// Adding identity point should not change result
212-
let c = c_1.to_extensible().add_extended(&ExtendedPoint::IDENTITY);
213-
assert!(c.to_extended() == c_1);
296+
let c = c_1.add_extended(&ExtendedPoint::IDENTITY);
297+
assert!(c == c_1);
214298
}
215299

216300
#[test]
217301
fn test_point_sub() {
218302
let a = TWISTED_EDWARDS_BASE_POINT;
219-
let b = a.double();
303+
let b = a.to_extensible().double().to_extended();
220304

221305
// A - B = C
222-
let c_1 = a.to_extensible().sub_extended(&b).to_extended();
306+
let c_1 = a.sub_extended(&b).to_extended();
223307

224308
// -B + A = C
225-
let c_2 = b.negate().to_extensible().add_extended(&a).to_extended();
309+
let c_2 = b.negate().add_extended(&a).to_extended();
226310
assert!(c_1 == c_2);
227311
}
228312

@@ -231,6 +315,6 @@ mod tests {
231315
let a = TWISTED_EDWARDS_BASE_POINT;
232316
let neg_a = a.negate();
233317

234-
assert!(a.to_extensible().add_extended(&neg_a) == ExtensiblePoint::IDENTITY);
318+
assert!(a.add_extended(&neg_a) == ExtensiblePoint::IDENTITY);
235319
}
236320
}

0 commit comments

Comments
 (0)