@@ -86,35 +86,48 @@ impl AffinePoint {
8686 }
8787 }
8888
89+ // https://www.rfc-editor.org/rfc/rfc7748#section-4.2
8990 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 }
118131 }
119132
120133 /// Standard compression; store Y and sign of X
0 commit comments