@@ -8,37 +8,44 @@ use subtle::{Choice, ConditionallySelectable};
8
8
9
9
use super :: { MontgomeryPoint , MontgomeryScalar , ProjectiveMontgomeryPoint } ;
10
10
11
+ #[ allow( non_upper_case_globals) ]
12
+ const s: FieldElement = FieldElement ( ConstMontyType :: new ( & U448 :: from_u64 ( 3 ) ) ) ;
13
+
11
14
impl Add < & ProjectiveMontgomeryPoint > for & ProjectiveMontgomeryPoint {
12
15
type Output = ProjectiveMontgomeryPoint ;
13
16
14
- // Copied from https://github.com/armfazh/redox-ecc/blob/5a8c09c5ef9fe6a8d2c749d05eca011c6d661599/src/montgomery/point.rs#L80-L104.
17
+ // See Complete Addition Law for Montgomery Curves - Algorithm 1.
18
+ // With "Trade-Off Technique".
15
19
fn add ( self , rhs : & ProjectiveMontgomeryPoint ) -> Self :: Output {
16
- const S : FieldElement = FieldElement ( ConstMontyType :: new ( & U448 :: from_u64 ( 3 ) ) ) ;
17
-
18
20
let ( x1, y1, z1) = ( self . U , self . V , self . W ) ;
19
21
let ( x2, y2, z2) = ( rhs. U , rhs. V , rhs. W ) ;
20
- let ( a_ec, s_ec) = ( FieldElement :: J , S ) ;
21
- let ( t0, t1, t2) = ( x1 * x2, y1 * y2, z1 * z2) ;
22
- let ( t3, t4) = ( x1 * y2, x2 * y1) ;
23
- let ( t5, t6) = ( y1 * z2, y2 * z1) ;
24
- let ( t7, t8) = ( x1 * z2, x2 * z1) ;
25
- let t9 = t7 + t8;
26
- let ta = t9 + ( t0 * a_ec) ;
27
- let rr = t5 + t6;
28
- let tt = ta - t1;
29
- let vv = t9 * a_ec + t0. double ( ) + t0 + t2;
30
- let ss = ( t3 - t4) * s_ec + t0 - t2;
31
- let uu = ( t7 - t8) * s_ec - t3 - t4;
32
- let ww = ( t5 - t6) * s_ec + ta + t1;
33
- let x3 = rr * ss - tt * uu;
34
- let y3 = tt * ww - vv * ss;
35
- let z3 = vv * uu - rr * ww;
36
22
37
- ProjectiveMontgomeryPoint {
38
- U : x3,
39
- V : y3,
40
- W : z3,
41
- }
23
+ let t0 = x1 * x2;
24
+ let t1 = y1 * y2;
25
+ let t2 = z1 * z2;
26
+ let t3 = x1 * y2;
27
+ let t4 = x2 * y1;
28
+ let t5 = y1 * z2;
29
+ let t6 = y2 * z1;
30
+ let t7 = x1 * z2;
31
+ let t8 = x2 * z1;
32
+ let t9 = t7 + t8;
33
+ let t10 = t9 + FieldElement :: J * t0;
34
+ let R = t5 + t6;
35
+ let T = t10 - t1;
36
+ let V = FieldElement :: J * t9 + t0. double ( ) + t0 + t2;
37
+ let S = s * ( t3 - t4) + t0 - t2;
38
+ let U = s * ( t7 - t8) - t3 - t4;
39
+ let W = s * ( t5 - t6) + t10 + t1;
40
+ let C = ( R + T ) * ( S - U ) ;
41
+ let D = ( R - T ) * ( S + U ) ;
42
+ let E = ( T + V ) * ( W - S ) ;
43
+ let F = ( T - V ) * ( W + S ) ;
44
+ let X = C + D ;
45
+ let Y = E + F ;
46
+ let Z = ( U - W ) . double ( ) * ( R + V ) + C - D + E - F ;
47
+
48
+ ProjectiveMontgomeryPoint { U : X , V : Y , W : Z }
42
49
}
43
50
}
44
51
@@ -51,8 +58,38 @@ define_add_variants!(
51
58
impl Add < & MontgomeryPoint > for & ProjectiveMontgomeryPoint {
52
59
type Output = ProjectiveMontgomeryPoint ;
53
60
54
- fn add ( self , other : & MontgomeryPoint ) -> ProjectiveMontgomeryPoint {
55
- * self + * other
61
+ // See Complete Addition Law for Montgomery Curves - Algorithm 1.
62
+ // With "Trade-Off Technique".
63
+ fn add ( self , rhs : & MontgomeryPoint ) -> ProjectiveMontgomeryPoint {
64
+ let ( x1, y1, z1) = ( self . U , self . V , self . W ) ;
65
+ let ( x2, y2) = ( rhs. x , rhs. y ) ;
66
+
67
+ let t0 = x1 * x2;
68
+ let t1 = y1 * y2;
69
+ let t2 = z1;
70
+ let t3 = x1 * y2;
71
+ let t4 = x2 * y1;
72
+ let t5 = y1;
73
+ let t6 = y2 * z1;
74
+ let t7 = x1;
75
+ let t8 = x2 * z1;
76
+ let t9 = t7 + t8;
77
+ let t10 = t9 + FieldElement :: J * t0;
78
+ let R = t5 + t6;
79
+ let T = t10 - t1;
80
+ let V = FieldElement :: J * t9 + t0. double ( ) + t0 + t2;
81
+ let S = s * ( t3 - t4) + t0 - t2;
82
+ let U = s * ( t7 - t8) - t3 - t4;
83
+ let W = s * ( t5 - t6) + t10 + t1;
84
+ let C = ( R + T ) * ( S - U ) ;
85
+ let D = ( R - T ) * ( S + U ) ;
86
+ let E = ( T + V ) * ( W - S ) ;
87
+ let F = ( T - V ) * ( W + S ) ;
88
+ let X = C + D ;
89
+ let Y = E + F ;
90
+ let Z = ( U - W ) . double ( ) * ( R + V ) + C - D + E - F ;
91
+
92
+ ProjectiveMontgomeryPoint { U : X , V : Y , W : Z }
56
93
}
57
94
}
58
95
@@ -66,7 +103,7 @@ impl Add<&ProjectiveMontgomeryPoint> for &MontgomeryPoint {
66
103
type Output = ProjectiveMontgomeryPoint ;
67
104
68
105
fn add ( self , other : & ProjectiveMontgomeryPoint ) -> ProjectiveMontgomeryPoint {
69
- * other + * self
106
+ other + self
70
107
}
71
108
}
72
109
@@ -111,9 +148,9 @@ impl Mul<&MontgomeryScalar> for &ProjectiveMontgomeryPoint {
111
148
let mut p = ProjectiveMontgomeryPoint :: IDENTITY ;
112
149
let bits = scalar. bits ( ) ;
113
150
114
- for s in ( 0 ..448 ) . rev ( ) {
151
+ for index in ( 0 ..448 ) . rev ( ) {
115
152
p = p + p;
116
- p. conditional_assign ( & ( p + self ) , Choice :: from ( bits[ s ] as u8 ) ) ;
153
+ p. conditional_assign ( & ( p + self ) , Choice :: from ( bits[ index ] as u8 ) ) ;
117
154
}
118
155
119
156
p
@@ -264,3 +301,20 @@ where
264
301
iter. fold ( Self :: IDENTITY , |acc, item| acc + item. borrow ( ) )
265
302
}
266
303
}
304
+
305
+ #[ cfg( test) ]
306
+ mod test {
307
+ use elliptic_curve:: Group ;
308
+ use rand_core:: OsRng ;
309
+
310
+ use super :: * ;
311
+
312
+ #[ test]
313
+ fn mixed_addition ( ) {
314
+ let p1 = ProjectiveMontgomeryPoint :: try_from_rng ( & mut OsRng ) . unwrap ( ) ;
315
+ let p2 = ProjectiveMontgomeryPoint :: try_from_rng ( & mut OsRng ) . unwrap ( ) ;
316
+ let p3 = p1 + p2;
317
+
318
+ assert_eq ! ( p3. to_affine( ) , ( p1. to_affine( ) + p2) . to_affine( ) ) ;
319
+ }
320
+ }
0 commit comments