@@ -86,35 +86,48 @@ impl AffinePoint {
86
86
}
87
87
}
88
88
89
+ // https://www.rfc-editor.org/rfc/rfc7748#section-4.2
89
90
pub ( crate ) fn isogeny ( & self ) -> Self {
90
- let x = self . x ;
91
- let y = self . y ;
92
- let mut t0 = x. square ( ) ; // x^2
93
- let t1 = t0 + FieldElement :: ONE ; // x^2+1
94
- t0 -= FieldElement :: ONE ; // x^2-1
95
- let mut t2 = y. square ( ) ; // y^2
96
- t2 = t2. double ( ) ; // 2y^2
97
- let t3 = x. double ( ) ; // 2x
98
-
99
- let mut t4 = t0 * y; // y(x^2-1)
100
- t4 = t4. double ( ) ; // 2y(x^2-1)
101
- let xNum = t4. double ( ) ; // xNum = 4y(x^2-1)
102
-
103
- let mut t5 = t0. square ( ) ; // x^4-2x^2+1
104
- t4 = t5 + t2; // x^4-2x^2+1+2y^2
105
- let xDen = t4 + t2; // xDen = x^4-2x^2+1+4y^2
106
-
107
- t5 *= x; // x^5-2x^3+x
108
- t4 = t2 * t3; // 4xy^2
109
- let yNum = t4 - t5; // yNum = -(x^5-2x^3+x-4xy^2)
110
-
111
- t4 = t1 * t2; // 2x^2y^2+2y^2
112
- let yDen = t5 - t4; // yDen = x^5-2x^3+x-2x^2y^2-2y^2
113
-
114
- Self {
115
- x : xNum * xDen. invert ( ) ,
116
- y : yNum * yDen. invert ( ) ,
117
- }
91
+ let u = self . x ;
92
+ let v = self . y ;
93
+
94
+ // x = (4*v*(u^2 - 1)/(u^4 - 2*u^2 + 4*v^2 + 1)
95
+ // y = -(u^5 - 2*u^3 - 4*u*v^2 + u)/(u^5 - 2*u^2*v^2 - 2*u^3 - 2*v^2 + u))
96
+
97
+ let uu = u. square ( ) ;
98
+ let uu_minus_1 = uu - FieldElement :: ONE ;
99
+ let uu_minus_1_sq = uu_minus_1. square ( ) ;
100
+ let vv2 = v. square ( ) . double ( ) ;
101
+ let vv4 = vv2. double ( ) ;
102
+
103
+ // 4*v*(u^2 - 1)
104
+ let xn = v. double ( ) . double ( ) * uu_minus_1;
105
+ // u^4 - 2*u^2 + 4*v^2 + 1
106
+ // Simplified to:
107
+ // = u^4 - 2*u^2 + 1 + 4*v^2
108
+ // = (u^2 - 1)^2 - 4*v^2 | (perfect square trinomial)
109
+ let xd = uu_minus_1_sq + vv4;
110
+
111
+ // -(u^5 - 2*u^3 - 4*u*v^2 + u)
112
+ // Simplified to:
113
+ // = -u * (u^4 - 2*u^2 - 4*v^2 + 1)
114
+ // = -u * (u^4 - 2*u^2 + 1 - 4*v^2)
115
+ // = -u * ((u^2 - 1)^2 - 4*v^2) | (perfect square trinomial)
116
+ let yn = -u * ( uu_minus_1_sq - vv4) ;
117
+ // u^5 - 2*u^2*v^2 - 2*u^3 - 2*v^2 + u
118
+ // Simplified to:
119
+ // = u^5 - 2*u^3 + u - 2*u^2*v^2 - 2*v^2
120
+ // = u * (u^4 - 2*u^2 + 1) - 2*v^2 * (u^2 + 1)
121
+ // = u * (u^2 - 1)^2 - 2*v^2 * (u^2 + 1) | (perfect square trinomial)
122
+ let yd = u * uu_minus_1_sq - vv2 * ( uu + FieldElement :: ONE ) ;
123
+
124
+ // Simplified two denominators to a single inversion.
125
+ let d = ( xd * yd) . invert ( ) ;
126
+
127
+ let x = xn * yd * d;
128
+ let y = yn * xd * d;
129
+
130
+ Self { x, y }
118
131
}
119
132
120
133
/// Standard compression; store Y and sign of X
0 commit comments