diff --git a/src/bls12_381/ec.rs b/src/bls12_381/ec.rs index f441cca..16c5401 100644 --- a/src/bls12_381/ec.rs +++ b/src/bls12_381/ec.rs @@ -85,6 +85,33 @@ macro_rules! curve_impl { } impl $affine { + /// Constructs an affine point with the lexicographically smallest + /// y-coordinate, given an x-coordinate, so long as the x-coordinate + /// exists on the curve. The point is not guaranteed to be in the + /// prime order subgroup. + fn get_point_from_x(x: $basefield) -> Option<$affine> { + // Compute x^3 + b + let mut x3b = x; + x3b.square(); + x3b.mul_assign(&x); + x3b.add_assign(&$affine::get_coeff_b()); + + x3b.sqrt().map(|y| { + let mut negy = y; + negy.negate(); + + $affine { + x: x, + y: if y < negy { + y + } else { + negy + }, + infinity: false + } + }) + } + fn is_on_curve(&self) -> bool { if self.is_zero() { true @@ -781,26 +808,13 @@ pub mod g1 { // Interpret as Fq element. let x = Fq::from_repr(x).map_err(|e| GroupDecodingError::CoordinateDecodingError("x coordinate", e))?; - // Compute x^3 + b - let mut x3b = x; - x3b.square(); - x3b.mul_assign(&x); - x3b.add_assign(&G1Affine::get_coeff_b()); - - // Attempt to compute y - match x3b.sqrt() { - Some(y) => { - let mut negy = y; - negy.negate(); - - // Get the parity of the sqrt we found. - let parity = y > negy; - - Ok(G1Affine { - x: x, - y: if parity == greatest { y } else { negy }, - infinity: false - }) + match G1Affine::get_point_from_x(x) { + Some(mut p) => { + if greatest { + p.negate(); + } + + Ok(p) }, None => { // Point must not be on the curve. @@ -1307,26 +1321,13 @@ pub mod g2 { c1: Fq::from_repr(x_c1).map_err(|e| GroupDecodingError::CoordinateDecodingError("x coordinate (c1)", e))? }; - // Compute x^3 + b - let mut x3b = x; - x3b.square(); - x3b.mul_assign(&x); - x3b.add_assign(&G2Affine::get_coeff_b()); - - // Attempt to compute y - match x3b.sqrt() { - Some(y) => { - let mut negy = y; - negy.negate(); - - // Get the parity of the sqrt we found. - let parity = y > negy; - - Ok(G2Affine { - x: x, - y: if parity == greatest { y } else { negy }, - infinity: false - }) + match G2Affine::get_point_from_x(x) { + Some(mut p) => { + if greatest { + p.negate(); + } + + Ok(p) }, None => { // Point must not be on the curve.