Replace (x, y) tuple with Coordinates struct

The previous `CurveAffine::get_xy` method returned the coordinates as
`CtOption<(C::Base, C::Base)>`. However, `ConditionallySelectable` is
not implemented for any tuple or array types, making it impossible to
use any of the useful `CtOption` methods like `and_then`. We replace it
with `CurveAffine::coordinates -> CtOption<Coordinates<Self>>` and
`impl ConditionallySelectable for Coordinates` to enable operating over
coordinates in constant time.
This commit is contained in:
Jack Grigg 2021-04-18 09:21:18 +12:00
parent 5ef94023a3
commit b016b972f8
2 changed files with 53 additions and 5 deletions

View file

@ -99,8 +99,10 @@ pub trait CurveAffine:
/// The projective form of the curve
type CurveExt: CurveExt<AffineExt = Self, ScalarExt = <Self as CurveAffine>::ScalarExt>;
/// Gets the $(x, y)$ coordinates of this point.
fn get_xy(&self) -> CtOption<(Self::Base, Self::Base)>;
/// Gets the coordinates of this point.
///
/// Returns None if this is the identity.
fn coordinates(&self) -> CtOption<Coordinates<Self>>;
/// Obtains a point given $(x, y)$, failing if it is not on the
/// curve.
@ -131,3 +133,49 @@ pub trait CurveAffine:
/// Returns the curve constant $b$.
fn b() -> Self::Base;
}
/// The affine coordinates of a point on an elliptic curve.
#[derive(Clone, Copy, Debug, Default)]
pub struct Coordinates<C: CurveAffine> {
pub(crate) x: C::Base,
pub(crate) y: C::Base,
}
impl<C: CurveAffine> Coordinates<C> {
/// Returns the x-coordinate.
///
/// Equivalent to `Coordinates::u`.
pub fn x(&self) -> &C::Base {
&self.x
}
/// Returns the y-coordinate.
///
/// Equivalent to `Coordinates::v`.
pub fn y(&self) -> &C::Base {
&self.y
}
/// Returns the u-coordinate.
///
/// Equivalent to `Coordinates::x`.
pub fn u(&self) -> &C::Base {
&self.x
}
/// Returns the v-coordinate.
///
/// Equivalent to `Coordinates::y`.
pub fn v(&self) -> &C::Base {
&self.y
}
}
impl<C: CurveAffine> ConditionallySelectable for Coordinates<C> {
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
Coordinates {
x: C::Base::conditional_select(&a.x, &b.x, choice),
y: C::Base::conditional_select(&a.y, &b.y, choice),
}
}
}

View file

@ -15,7 +15,7 @@ use rand::RngCore;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use super::{Fp, Fq};
use crate::arithmetic::{CurveAffine, CurveExt, FieldExt, Group};
use crate::arithmetic::{Coordinates, CurveAffine, CurveExt, FieldExt, Group};
macro_rules! new_curve_impl {
(($($privacy:tt)*), $name:ident, $name_affine:ident, $iso:ident, $base:ident, $scalar:ident,
@ -653,8 +653,8 @@ macro_rules! new_curve_impl {
| self.infinity
}
fn get_xy(&self) -> CtOption<(Self::Base, Self::Base)> {
CtOption::new((self.x, self.y), !self.is_identity())
fn coordinates(&self) -> CtOption<Coordinates<Self>> {
CtOption::new(Coordinates { x: self.x, y: self.y }, !self.is_identity())
}
fn from_xy(x: Self::Base, y: Self::Base) -> CtOption<Self> {