TwistedEdwardsCoordinates {
+ /// Obtains a `TwistedEdwardsCoordinates` value given $(x, y)$, failing if it is not
+ /// on the curve.
+ pub fn from_coordinates(x: P::Base, y: P::Base) -> CtOption {
+ // We use `P::from_bare_coordinates` to validate the coordinates.
+ P::from_bare_coordinates(x, y).map(|_| TwistedEdwardsCoordinates { x, y })
+ }
+
+ /// Returns the x-coordinate.
+ pub fn x(&self) -> P::Base {
+ self.x
+ }
+
+ /// Returns the y-coordinate.
+ pub fn y(&self) -> P::Base {
+ self.y
+ }
+}
+
+impl ConditionallySelectable for TwistedEdwardsCoordinates {
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ TwistedEdwardsCoordinates {
+ x: P::Base::conditional_select(&a.x, &b.x, choice),
+ y: P::Base::conditional_select(&a.y, &b.y, choice),
+ }
+ }
+}
+
+//
+// Montgomery curve
+//
+
+/// An affine elliptic curve point on a Montgomery curve
+/// $B \cdot v^2 = u^3 + A \cdot u^2 + u$.
+///
+/// For these curves, it is required that $B \cdot (A^2 - 4) ≠ 0$, which implies that
+/// $A ≠ ±2$ and $B ≠ 0$.
+pub trait MontgomeryPoint: CurveAffine + Default + ConditionallySelectable {
+ /// Field element type used in the curve equation.
+ type Base: Copy + ConditionallySelectable;
+
+ /// The parameter $A$ in the Montgomery curve equation.
+ const A: Self::Base;
+
+ /// The parameter $B$ in the Montgomery curve equation.
+ const B: Self::Base;
+
+ /// Obtains a point given $(u, v)$, failing if it is not on the curve.
+ fn from_bare_coordinates(u: Self::Base, v: Self::Base) -> CtOption;
+
+ /// Obtains a point given its coordinates.
+ fn from_coordinates(coords: MontgomeryCoordinates) -> Self;
+
+ /// Returns the coordinates of this point.
+ ///
+ /// Returns `None` if this is the identity.
+ fn coordinates(&self) -> CtOption>;
+}
+
+/// The affine coordinates for a [`MontgomeryCoordinates`].
+#[derive(Clone, Copy, Debug, Default)]
+pub struct MontgomeryCoordinates {
+ u: P::Base,
+ v: P::Base,
+}
+
+impl MontgomeryCoordinates {
+ /// Obtains a `MontgomeryCoordinates` value given $(u, v)$, failing if it is not on
+ /// the curve.
+ pub fn from_coordinates(u: P::Base, v: P::Base) -> CtOption {
+ // We use `P::from_bare_coordinates` to validate the coordinates.
+ P::from_bare_coordinates(u, v).map(|_| MontgomeryCoordinates { u, v })
+ }
+
+ /// Returns the u-coordinate.
+ pub fn u(&self) -> P::Base {
+ self.u
+ }
+
+ /// Returns the v-coordinate.
+ pub fn v(&self) -> P::Base {
+ self.v
+ }
+}
+
+impl ConditionallySelectable for MontgomeryCoordinates {
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ MontgomeryCoordinates {
+ u: P::Base::conditional_select(&a.u, &b.u, choice),
+ v: P::Base::conditional_select(&a.v, &b.v, choice),
+ }
+ }
+}
+
+//
+// Short Weierstrass curve
+//
+
+/// An affine elliptic curve point on a short Weierstrass curve
+/// $y^2 = x^3 + a \cdot x + b$.
+pub trait ShortWeierstrassPoint: CurveAffine + Default + ConditionallySelectable {
+ /// Field element type used in the curve equation.
+ type Base: Copy + ConditionallySelectable;
+
+ /// The parameter $a$ in the short Weierstrass curve equation.
+ const A: Self::Base;
+
+ /// The parameter $b$ in the short Weierstrass curve equation.
+ const B: Self::Base;
+
+ /// Obtains a point given $(x, y)$, failing if it is not on the curve.
+ fn from_bare_coordinates(x: Self::Base, y: Self::Base) -> CtOption;
+
+ /// Obtains a point given its coordinates.
+ fn from_coordinates(coords: ShortWeierstrassCoordinates) -> Self;
+
+ /// Returns the coordinates of this point.
+ ///
+ /// Returns `None` if this is the identity.
+ fn coordinates(&self) -> CtOption>;
+}
+
+/// The affine coordinates for a [`ShortWeierstrassCoordinates`].
+#[derive(Clone, Copy, Debug, Default)]
+pub struct ShortWeierstrassCoordinates {
+ x: P::Base,
+ y: P::Base,
+}
+
+impl ShortWeierstrassCoordinates {
+ /// Obtains a `ShortWeierstrassCoordinates` value given $(x, y)$, failing if it is not
+ /// on the curve.
+ pub fn from_coordinates(x: P::Base, y: P::Base) -> CtOption {
+ // We use `P::from_bare_coordinates` to validate the coordinates.
+ P::from_bare_coordinates(x, y).map(|_| ShortWeierstrassCoordinates { x, y })
+ }
+
+ /// Returns the x-coordinate.
+ pub fn x(&self) -> P::Base {
+ self.x
+ }
+
+ /// Returns the y-coordinate.
+ pub fn y(&self) -> P::Base {
+ self.y
+ }
+}
+
+impl ConditionallySelectable for ShortWeierstrassCoordinates {
+ fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
+ ShortWeierstrassCoordinates {
+ x: P::Base::conditional_select(&a.x, &b.x, choice),
+ y: P::Base::conditional_select(&a.y, &b.y, choice),
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 27ed5c9..9ec208d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,6 +21,8 @@ pub mod prime;
#[cfg(feature = "tests")]
pub mod tests;
+pub mod coordinates;
+
#[cfg(feature = "alloc")]
mod wnaf;
#[cfg(feature = "alloc")]
@@ -92,16 +94,16 @@ pub trait Group:
fn double(&self) -> Self;
}
-/// Efficient representation of an elliptic curve point guaranteed.
-pub trait Curve:
- Group + GroupOps<::AffineRepr> + GroupOpsOwned<::AffineRepr>
-{
+/// Efficient representation of an elliptic curve point.
+pub trait Curve: Group + GroupOps + GroupOpsOwned {
/// The affine representation for this elliptic curve.
- type AffineRepr;
+ type Affine: CurveAffine
+ + Mul
+ + for<'r> Mul<&'r Self::Scalar, Output = Self>;
/// Converts a batch of projective elements into affine elements. This function will
/// panic if `p.len() != q.len()`.
- fn batch_normalize(p: &[Self], q: &mut [Self::AffineRepr]) {
+ fn batch_normalize(p: &[Self], q: &mut [Self::Affine]) {
assert_eq!(p.len(), q.len());
for (p, q) in p.iter().zip(q.iter_mut()) {
@@ -110,7 +112,42 @@ pub trait Curve:
}
/// Converts this element into its affine representation.
- fn to_affine(&self) -> Self::AffineRepr;
+ fn to_affine(&self) -> Self::Affine;
+}
+
+/// Affine representation of an elliptic curve point.
+pub trait CurveAffine:
+ GroupEncoding
+ + Copy
+ + fmt::Debug
+ + Eq
+ + Send
+ + Sync
+ + 'static
+ + Neg