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