From b016b972f8ef0eeff6b31e5dc01bccb833937dcf Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 18 Apr 2021 09:21:18 +1200 Subject: [PATCH] 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>` and `impl ConditionallySelectable for Coordinates` to enable operating over coordinates in constant time. --- src/arithmetic/curves.rs | 52 ++++++++++++++++++++++++++++++++++++++-- src/curves.rs | 6 ++--- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/arithmetic/curves.rs b/src/arithmetic/curves.rs index 8dba212..a0b34ed 100644 --- a/src/arithmetic/curves.rs +++ b/src/arithmetic/curves.rs @@ -99,8 +99,10 @@ pub trait CurveAffine: /// The projective form of the curve type CurveExt: CurveExt::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>; /// 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 { + pub(crate) x: C::Base, + pub(crate) y: C::Base, +} + +impl Coordinates { + /// 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 ConditionallySelectable for Coordinates { + 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), + } + } +} diff --git a/src/curves.rs b/src/curves.rs index 6f64797..047c799 100644 --- a/src/curves.rs +++ b/src/curves.rs @@ -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> { + CtOption::new(Coordinates { x: self.x, y: self.y }, !self.is_identity()) } fn from_xy(x: Self::Base, y: Self::Base) -> CtOption {