@@ -4,7 +4,7 @@ use crate::edwards::extended::EdwardsPoint;
4
4
use crate :: field:: FieldElement ;
5
5
use core:: fmt;
6
6
use core:: ops:: Mul ;
7
- use subtle:: { Choice , ConditionallySelectable , ConstantTimeEq } ;
7
+ use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq } ;
8
8
9
9
// Low order points on Curve448 and it's twist
10
10
const LOW_A : MontgomeryXpoint = MontgomeryXpoint ( [
@@ -127,6 +127,11 @@ impl MontgomeryXpoint {
127
127
& self . 0
128
128
}
129
129
130
+ /// Compute the Y-coordinate
131
+ pub fn y ( & self , sign : Choice ) -> [ u8 ; 56 ] {
132
+ self . to_projective ( ) . y ( sign) . to_bytes ( )
133
+ }
134
+
130
135
/// Convert the point to a ProjectiveMontgomeryPoint
131
136
pub fn to_projective ( & self ) -> ProjectiveMontgomeryXpoint {
132
137
ProjectiveMontgomeryXpoint {
@@ -224,6 +229,18 @@ impl ProjectiveMontgomeryXpoint {
224
229
}
225
230
}
226
231
232
+ /// Compute the Y-coordinate
233
+ // See https://www.rfc-editor.org/rfc/rfc7748#section-1.
234
+ pub fn y ( & self , sign : Choice ) -> FieldElement {
235
+ // v^2 = u^3 + A*u^2 + u
236
+ let u_sq = self . U . square ( ) ;
237
+ let v_sq = u_sq * self . U + FieldElement :: J * u_sq + self . U ;
238
+
239
+ let mut v = v_sq. sqrt ( ) ;
240
+ v. conditional_negate ( v. is_negative ( ) ^ sign) ;
241
+ v
242
+ }
243
+
227
244
/// Convert the point to affine form
228
245
pub fn to_affine ( & self ) -> MontgomeryXpoint {
229
246
let x = self . U * self . W . invert ( ) ;
0 commit comments