From 0b11bc72baf59365371ce8cefb1014f2dcbc91ec Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Mon, 6 Feb 2023 16:23:31 +0000 Subject: [PATCH 1/4] Introduce PointArithmetic trait --- primeorder/src/equation_a.rs | 34 --- primeorder/src/lib.rs | 6 +- primeorder/src/point_arithmetic.rs | 327 +++++++++++++++++++++++++++++ primeorder/src/projective.rs | 107 +--------- 4 files changed, 338 insertions(+), 136 deletions(-) delete mode 100644 primeorder/src/equation_a.rs create mode 100644 primeorder/src/point_arithmetic.rs diff --git a/primeorder/src/equation_a.rs b/primeorder/src/equation_a.rs deleted file mode 100644 index a8b76aa02..000000000 --- a/primeorder/src/equation_a.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Support for formulas specialized to the short Weierstrass equation's -//! 𝒂-coefficient. -//! -//! This module is largely a workaround for things which should be possible -//! to implement more elegantly with future Rust features like -//! `generic_const_exprs` and `impl const Trait`. -//! -//! In absence of such features, we define ZSTs that identify properties of -//! the 𝒂-coefficient which could potentially be written as const expressions -//! on `PrimeCurveParams::EQUATION_A` in the future (including ones which -//! could be used as trait bounds). - -mod sealed { - /// Sealed trait which identifies special properties of the curve's - /// 𝒂-coefficient. - pub trait EquationAProperties {} -} - -// Allow crate-local visibility -pub(crate) use sealed::EquationAProperties; - -/// The 𝒂-coefficient of the short Weierstrass equation is 0. -pub struct IsZero {} - -/// The 𝒂-coefficient of the short Weierstrass equation is -3. -pub struct IsMinusThree {} - -/// The 𝒂-coefficient of the short Weierstrass equation does not have specific -/// properties which allow for an optimized implementation. -pub struct IsGeneric {} - -impl EquationAProperties for IsZero {} -impl EquationAProperties for IsMinusThree {} -impl EquationAProperties for IsGeneric {} diff --git a/primeorder/src/lib.rs b/primeorder/src/lib.rs index c3124067f..c19413d19 100644 --- a/primeorder/src/lib.rs +++ b/primeorder/src/lib.rs @@ -8,7 +8,7 @@ #![warn(missing_docs, rust_2018_idioms, unused_qualifications)] #![doc = include_str!("../README.md")] -pub mod equation_a; +pub mod point_arithmetic; mod affine; mod field; @@ -30,8 +30,8 @@ pub trait PrimeCurveParams: /// Base field element type. type FieldElement: PrimeField>; - /// Special properties of the `a`-coefficient. - type EquationAProperties: equation_a::EquationAProperties; + /// [Point arithmetic](point_arithmetic) implementation, might be optimized for this specific curve + type PointArithmetic: point_arithmetic::PointArithmetic; /// Coefficient `a` in the curve equation. const EQUATION_A: Self::FieldElement; diff --git a/primeorder/src/point_arithmetic.rs b/primeorder/src/point_arithmetic.rs new file mode 100644 index 000000000..0faad6eff --- /dev/null +++ b/primeorder/src/point_arithmetic.rs @@ -0,0 +1,327 @@ +//! Point arithmetic implementation optimised for different curve equations +//! +//! Support for formulas specialized to the short Weierstrass equation's +//! 𝒂-coefficient. +//! +//! This module is largely a workaround for things which should be possible +//! to implement more elegantly with future Rust features like +//! `generic_const_exprs` and `impl const Trait`. +//! +//! In absence of such features, we define ZSTs that implement point arithmetic +//! for different curve equations that depend on properties of the 𝒂-coefficient +//! which could potentially be written as const expressions on `PrimeCurveParams::EQUATION_A` +//! in the future (including ones which could be used as trait bounds). + +use elliptic_curve::{subtle::ConditionallySelectable, Field}; + +use crate::{AffinePoint, PrimeCurveParams, ProjectivePoint}; + +mod sealed { + /// Seals `PointArithmetic` trait + pub trait Sealed {} +} + +/// Elliptic point artihmetic implementation +/// +/// Provides implementation of point arithmetic (point addition, point doubling) which +/// might be optimized for the curve. +pub trait PointArithmetic: sealed::Sealed { + /// Returns `point + point` + fn double(point: &ProjectivePoint) -> ProjectivePoint; + /// Returns `lhs + rhs` + fn add(lhs: &ProjectivePoint, rhs: &ProjectivePoint) -> ProjectivePoint; + /// Returns `lhs + rhs` + fn add_mixed(lhs: &ProjectivePoint, rhs: &AffinePoint) -> ProjectivePoint; +} + +/// The 𝒂-coefficient of the short Weierstrass equation is -3. +pub struct EquationAIsMinusThree {} + +impl sealed::Sealed for EquationAIsMinusThree {} + +impl PointArithmetic for EquationAIsMinusThree { + /// Implements point doubling for curves with `a = -3` + /// + /// Implements the exception-free point doubling formula from [Renes-Costello-Batina 2015] + /// (Algorithm 6). The comments after each line indicate which algorithm + /// steps are being performed. + /// + /// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060 + fn double(point: &ProjectivePoint) -> ProjectivePoint { + debug_assert_eq!( + C::EQUATION_A, + -C::FieldElement::from(3), + "this implementation is only valid for C::EQUATION_A = -3" + ); + + let xx = point.x.square(); // 1 + let yy = point.y.square(); // 2 + let zz = point.z.square(); // 3 + let xy2 = (point.x * &point.y).double(); // 4, 5 + let xz2 = (point.x * &point.z).double(); // 6, 7 + + let bzz_part = (C::EQUATION_B * &zz) - &xz2; // 8, 9 + let bzz3_part = bzz_part.double() + &bzz_part; // 10, 11 + let yy_m_bzz3 = yy - &bzz3_part; // 12 + let yy_p_bzz3 = yy + &bzz3_part; // 13 + let y_frag = yy_p_bzz3 * &yy_m_bzz3; // 14 + let x_frag = yy_m_bzz3 * &xy2; // 15 + + let zz3 = zz.double() + &zz; // 16, 17 + let bxz2_part = (C::EQUATION_B * &xz2) - &(zz3 + &xx); // 18, 19, 20 + let bxz6_part = bxz2_part.double() + &bxz2_part; // 21, 22 + let xx3_m_zz3 = xx.double() + &xx - &zz3; // 23, 24, 25 + + let y = y_frag + &(xx3_m_zz3 * &bxz6_part); // 26, 27 + let yz2 = (point.y * &point.z).double(); // 28, 29 + let x = x_frag - &(bxz6_part * &yz2); // 30, 31 + let z = (yz2 * &yy).double().double(); // 32, 33, 34 + + ProjectivePoint { x, y, z } + } + + /// Implements complete addition for curves with `a = -3` + /// + /// Implements the complete addition formula from [Renes-Costello-Batina 2015] + /// (Algorithm 4). The comments after each line indicate which algorithm steps + /// are being performed. + /// + /// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060 + fn add(lhs: &ProjectivePoint, rhs: &ProjectivePoint) -> ProjectivePoint { + debug_assert_eq!( + C::EQUATION_A, + -C::FieldElement::from(3), + "this implementation is only valid for C::EQUATION_A = -3" + ); + + let xx = lhs.x * &rhs.x; // 1 + let yy = lhs.y * &rhs.y; // 2 + let zz = lhs.z * &rhs.z; // 3 + let xy_pairs = ((lhs.x + &lhs.y) * &(rhs.x + &rhs.y)) - &(xx + &yy); // 4, 5, 6, 7, 8 + let yz_pairs = ((lhs.y + &lhs.z) * &(rhs.y + &rhs.z)) - &(yy + &zz); // 9, 10, 11, 12, 13 + let xz_pairs = ((lhs.x + &lhs.z) * &(rhs.x + &rhs.z)) - &(xx + &zz); // 14, 15, 16, 17, 18 + + let bzz_part = xz_pairs - &(C::EQUATION_B * &zz); // 19, 20 + let bzz3_part = bzz_part.double() + &bzz_part; // 21, 22 + let yy_m_bzz3 = yy - &bzz3_part; // 23 + let yy_p_bzz3 = yy + &bzz3_part; // 24 + + let zz3 = zz.double() + &zz; // 26, 27 + let bxz_part = (C::EQUATION_B * &xz_pairs) - &(zz3 + &xx); // 25, 28, 29 + let bxz3_part = bxz_part.double() + &bxz_part; // 30, 31 + let xx3_m_zz3 = xx.double() + &xx - &zz3; // 32, 33, 34 + + ProjectivePoint { + x: (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 35, 39, 40 + y: (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 36, 37, 38 + z: (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 41, 42, 43 + } + } + + /// Implements complete mixed addition for curves with `a = -3` + /// + /// Implements the complete mixed addition formula from [Renes-Costello-Batina 2015] + /// (Algorithm 5). The comments after each line indicate which algorithm + /// steps are being performed. + /// + /// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060 + fn add_mixed(lhs: &ProjectivePoint, rhs: &AffinePoint) -> ProjectivePoint { + debug_assert_eq!( + C::EQUATION_A, + -C::FieldElement::from(3), + "this implementation is only valid for C::EQUATION_A = -3" + ); + + let xx = lhs.x * &rhs.x; // 1 + let yy = lhs.y * &rhs.y; // 2 + let xy_pairs = ((lhs.x + &lhs.y) * &(rhs.x + &rhs.y)) - &(xx + &yy); // 3, 4, 5, 6, 7 + let yz_pairs = (rhs.y * &lhs.z) + &lhs.y; // 8, 9 (t4) + let xz_pairs = (rhs.x * &lhs.z) + &lhs.x; // 10, 11 (y3) + + let bz_part = xz_pairs - &(C::EQUATION_B * &lhs.z); // 12, 13 + let bz3_part = bz_part.double() + &bz_part; // 14, 15 + let yy_m_bzz3 = yy - &bz3_part; // 16 + let yy_p_bzz3 = yy + &bz3_part; // 17 + + let z3 = lhs.z.double() + &lhs.z; // 19, 20 + let bxz_part = (C::EQUATION_B * &xz_pairs) - &(z3 + &xx); // 18, 21, 22 + let bxz3_part = bxz_part.double() + &bxz_part; // 23, 24 + let xx3_m_zz3 = xx.double() + &xx - &z3; // 25, 26, 27 + + let mut ret = ProjectivePoint { + x: (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 28, 32, 33 + y: (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 29, 30, 31 + z: (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 34, 35, 36 + }; + ret.conditional_assign(lhs, rhs.is_identity()); + ret + } +} + +/// The 𝒂-coefficient of the short Weierstrass equation does not have specific +/// properties which allow for an optimized implementation. +pub struct EquationAIsGeneric {} + +impl sealed::Sealed for EquationAIsGeneric {} + +impl PointArithmetic for EquationAIsGeneric { + /// Implements point doubling for curves with any `a` + /// + /// Implements the exception-free point doubling formula from [Renes-Costello-Batina 2015] + /// (Algorithm 3). The comments after each line indicate which algorithm + /// steps are being performed. + /// + /// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060 + fn double(point: &ProjectivePoint) -> ProjectivePoint { + let b3 = C::EQUATION_B * C::FieldElement::from(3); + + let t0 = point.x * &point.x; // 1 + let t1 = point.y * &point.y; // 2 + let t2 = point.z * &point.z; // 3 + let t3 = point.x * &point.y; // 4 + let t3 = t3 + &t3; // 5 + let z3 = point.x * &point.z; // 6 + let z3 = z3 + &z3; // 7 + let x3 = C::EQUATION_A * &z3; // 8 + let y3 = b3 * &t2; // 9 + let y3 = x3 + &y3; // 10 + let x3 = t1 - &y3; // 11 + let y3 = t1 + &y3; // 12 + let y3 = x3 * &y3; // 13 + let x3 = t3 * &x3; // 14 + let z3 = b3 * &z3; // 15 + let t2 = C::EQUATION_A * &t2; // 16 + let t3 = t0 - &t2; // 17 + let t3 = C::EQUATION_A * &t3; // 18 + let t3 = t3 + &z3; // 19 + let z3 = t0 + &t0; // 20 + let t0 = z3 + &t0; // 21 + let t0 = t0 + &t2; // 22 + let t0 = t0 * &t3; // 23 + let y3 = y3 + &t0; // 24 + let t2 = point.y * &point.z; // 25 + let t2 = t2 + &t2; // 26 + let t0 = t2 * &t3; // 27 + let x3 = x3 - &t0; // 28 + let z3 = t2 * &t1; // 29 + let z3 = z3 + &z3; // 30 + let z3 = z3 + &z3; // 31 + + ProjectivePoint { + x: x3, + y: y3, + z: z3, + } + } + + /// Implements complete addition for any curve + /// + /// Implements the complete addition formula from [Renes-Costello-Batina 2015] + /// (Algorithm 1). The comments after each line indicate which algorithm steps + /// are being performed. + /// + /// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060 + fn add(lhs: &ProjectivePoint, rhs: &ProjectivePoint) -> ProjectivePoint { + let b3 = C::FieldElement::from(3) * C::EQUATION_B; + + let t0 = lhs.x * &rhs.x; // 1 + let t1 = lhs.y * &rhs.y; // 2 + let t2 = lhs.z * &rhs.z; // 3 + let t3 = lhs.x + &lhs.y; // 4 + let t4 = rhs.x + &rhs.y; // 5 + let t3 = t3 * &t4; // 6 + let t4 = t0 + &t1; // 7 + let t3 = t3 - &t4; // 8 + let t4 = lhs.x + &lhs.z; // 9 + let t5 = rhs.x + &rhs.z; // 10 + let t4 = t4 * &t5; // 11 + let t5 = t0 + &t2; // 12 + let t4 = t4 - &t5; // 13 + let t5 = lhs.y + &lhs.z; // 14 + let x3 = rhs.y + &rhs.z; // 15 + let t5 = t5 * &x3; // 16 + let x3 = t1 + &t2; // 17 + let t5 = t5 - &x3; // 18 + let z3 = C::EQUATION_A * &t4; // 19 + let x3 = b3 * &t2; // 20 + let z3 = x3 + &z3; // 21 + let x3 = t1 - &z3; // 22 + let z3 = t1 + &z3; // 23 + let y3 = x3 * &z3; // 24 + let t1 = t0 + &t0; // 25 + let t1 = t1 + &t0; // 26 + let t2 = C::EQUATION_A * &t2; // 27 + let t4 = b3 * &t4; // 28 + let t1 = t1 + &t2; // 29 + let t2 = t0 - &t2; // 30 + let t2 = C::EQUATION_A * &t2; // 31 + let t4 = t4 + &t2; // 32 + let t0 = t1 * &t4; // 33 + let y3 = y3 + &t0; // 34 + let t0 = t5 * &t4; // 35 + let x3 = t3 * &x3; // 36 + let x3 = x3 - &t0; // 37 + let t0 = t3 * &t1; // 38 + let z3 = t5 * &z3; // 39 + let z3 = z3 + &t0; // 40 + + ProjectivePoint { + x: x3, + y: y3, + z: z3, + } + } + + /// Implements complete mixed addition for curves with any `a` + /// + /// Implements the complete mixed addition formula from [Renes-Costello-Batina 2015] + /// (Algorithm 2). The comments after each line indicate which algorithm + /// steps are being performed. + /// + /// [Renes-Costello-Batina 2015]: https://eprint.iacr.org/2015/1060 + fn add_mixed(lhs: &ProjectivePoint, rhs: &AffinePoint) -> ProjectivePoint { + let b3 = C::EQUATION_B * C::FieldElement::from(3); + + let t0 = lhs.x * &rhs.x; // 1 + let t1 = lhs.y * &rhs.y; // 2 + let t3 = rhs.x + &rhs.y; // 3 + let t4 = lhs.x + &lhs.y; // 4 + let t3 = t3 * &t4; // 5 + let t4 = t0 + &t1; // 6 + let t3 = t3 - &t4; // 7 + let t4 = rhs.x * &lhs.z; // 8 + let t4 = t4 + &lhs.x; // 9 + let t5 = rhs.y * &lhs.z; // 10 + let t5 = t5 + &lhs.y; // 11 + let z3 = C::EQUATION_A * &t4; // 12 + let x3 = b3 * &lhs.z; // 13 + let z3 = x3 + &z3; // 14 + let x3 = t1 - &z3; // 15 + let z3 = t1 + &z3; // 16 + let y3 = x3 * &z3; // 17 + let t1 = t0 + &t0; // 18 + let t1 = t1 + &t0; // 19 + let t2 = C::EQUATION_A * &lhs.z; // 20 + let t4 = b3 * &t4; // 21 + let t1 = t1 + &t2; // 22 + let t2 = t0 - &t2; // 23 + let t2 = C::EQUATION_A * &t2; // 24 + let t4 = t4 + &t2; // 25 + let t0 = t1 * &t4; // 26 + let y3 = y3 + &t0; // 27 + let t0 = t5 * &t4; // 28 + let x3 = t3 * &x3; // 29 + let x3 = x3 - &t0; // 30 + let t0 = t3 * &t1; // 31 + let z3 = t5 * &z3; // 32 + let z3 = z3 + &t0; // 33 + + let mut ret = ProjectivePoint { + x: x3, + y: y3, + z: z3, + }; + ret.conditional_assign(lhs, rhs.is_identity()); + ret + } +} diff --git a/primeorder/src/projective.rs b/primeorder/src/projective.rs index e73b70b55..5549543fc 100644 --- a/primeorder/src/projective.rs +++ b/primeorder/src/projective.rs @@ -2,7 +2,7 @@ #![allow(clippy::needless_range_loop, clippy::op_ref)] -use crate::{equation_a, AffinePoint, Field, PrimeCurveParams}; +use crate::{point_arithmetic::PointArithmetic, AffinePoint, Field, PrimeCurveParams}; use core::{ borrow::Borrow, iter::Sum, @@ -32,9 +32,9 @@ use elliptic_curve::{ /// Point on a Weierstrass curve in projective coordinates. #[derive(Clone, Copy, Debug)] pub struct ProjectivePoint { - x: C::FieldElement, - y: C::FieldElement, - z: C::FieldElement, + pub(crate) x: C::FieldElement, + pub(crate) y: C::FieldElement, + pub(crate) z: C::FieldElement, } impl ProjectivePoint @@ -78,63 +78,12 @@ where /// Returns `self + other`. pub fn add(&self, other: &Self) -> Self { - // We implement the complete addition formula from Renes-Costello-Batina 2015 - // (https://eprint.iacr.org/2015/1060 Algorithm 4). The comments after each line - // indicate which algorithm steps are being performed. - - let xx = self.x * &other.x; // 1 - let yy = self.y * &other.y; // 2 - let zz = self.z * &other.z; // 3 - let xy_pairs = ((self.x + &self.y) * &(other.x + &other.y)) - &(xx + &yy); // 4, 5, 6, 7, 8 - let yz_pairs = ((self.y + &self.z) * &(other.y + &other.z)) - &(yy + &zz); // 9, 10, 11, 12, 13 - let xz_pairs = ((self.x + &self.z) * &(other.x + &other.z)) - &(xx + &zz); // 14, 15, 16, 17, 18 - - let bzz_part = xz_pairs - &(C::EQUATION_B * &zz); // 19, 20 - let bzz3_part = bzz_part.double() + &bzz_part; // 21, 22 - let yy_m_bzz3 = yy - &bzz3_part; // 23 - let yy_p_bzz3 = yy + &bzz3_part; // 24 - - let zz3 = zz.double() + &zz; // 26, 27 - let bxz_part = (C::EQUATION_B * &xz_pairs) - &(zz3 + &xx); // 25, 28, 29 - let bxz3_part = bxz_part.double() + &bxz_part; // 30, 31 - let xx3_m_zz3 = xx.double() + &xx - &zz3; // 32, 33, 34 - - Self { - x: (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 35, 39, 40 - y: (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 36, 37, 38 - z: (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 41, 42, 43 - } + C::PointArithmetic::add(self, other) } /// Returns `self + other`. fn add_mixed(&self, other: &AffinePoint) -> Self { - // We implement the complete mixed addition formula from Renes-Costello-Batina - // 2015 (Algorithm 5). The comments after each line indicate which algorithm - // steps are being performed. - - let xx = self.x * &other.x; // 1 - let yy = self.y * &other.y; // 2 - let xy_pairs = ((self.x + &self.y) * &(other.x + &other.y)) - &(xx + &yy); // 3, 4, 5, 6, 7 - let yz_pairs = (other.y * &self.z) + &self.y; // 8, 9 (t4) - let xz_pairs = (other.x * &self.z) + &self.x; // 10, 11 (y3) - - let bz_part = xz_pairs - &(C::EQUATION_B * &self.z); // 12, 13 - let bz3_part = bz_part.double() + &bz_part; // 14, 15 - let yy_m_bzz3 = yy - &bz3_part; // 16 - let yy_p_bzz3 = yy + &bz3_part; // 17 - - let z3 = self.z.double() + &self.z; // 19, 20 - let bxz_part = (C::EQUATION_B * &xz_pairs) - &(z3 + &xx); // 18, 21, 22 - let bxz3_part = bxz_part.double() + &bxz_part; // 23, 24 - let xx3_m_zz3 = xx.double() + &xx - &z3; // 25, 26, 27 - - let mut ret = Self { - x: (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 28, 32, 33 - y: (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 29, 30, 31 - z: (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 34, 35, 36 - }; - ret.conditional_assign(self, other.is_identity()); - ret + C::PointArithmetic::add_mixed(self, other) } /// Returns `self - other`. @@ -252,49 +201,9 @@ where impl DefaultIsZeroes for ProjectivePoint where C: PrimeCurveParams {} -// TODO(tarcieri): impls for `equation_a::IsGeneric` and `equation_a::IsZero` -impl Double for ProjectivePoint -where - C: PrimeCurveParams, -{ - /// Adapted from Renes-Costello-Batina 2015 (Algorithm 6) - /// - /// Exception-free point doubling formula for prime order short Weierstrass - /// curves `y² = x³ + ax + b` where `a = -3`. - /// - /// The comments after each lines indicate which algorithm steps - /// are being performed. +impl Double for ProjectivePoint { fn double(&self) -> Self { - debug_assert_eq!( - C::EQUATION_A, - -C::FieldElement::from(3), - "this implementation is only valid for C::EQUATION_A = -3" - ); - - let xx = self.x.square(); // 1 - let yy = self.y.square(); // 2 - let zz = self.z.square(); // 3 - let xy2 = (self.x * &self.y).double(); // 4, 5 - let xz2 = (self.x * &self.z).double(); // 6, 7 - - let bzz_part = (C::EQUATION_B * &zz) - &xz2; // 8, 9 - let bzz3_part = bzz_part.double() + &bzz_part; // 10, 11 - let yy_m_bzz3 = yy - &bzz3_part; // 12 - let yy_p_bzz3 = yy + &bzz3_part; // 13 - let y_frag = yy_p_bzz3 * &yy_m_bzz3; // 14 - let x_frag = yy_m_bzz3 * &xy2; // 15 - - let zz3 = zz.double() + &zz; // 16, 17 - let bxz2_part = (C::EQUATION_B * &xz2) - &(zz3 + &xx); // 18, 19, 20 - let bxz6_part = bxz2_part.double() + &bxz2_part; // 21, 22 - let xx3_m_zz3 = xx.double() + &xx - &zz3; // 23, 24, 25 - - let y = y_frag + &(xx3_m_zz3 * &bxz6_part); // 26, 27 - let yz2 = (self.y * &self.z).double(); // 28, 29 - let x = x_frag - &(bxz6_part * &yz2); // 30, 31 - let z = (yz2 * &yy).double().double(); // 32, 33, 34 - - Self { x, y, z } + C::PointArithmetic::double(self) } } From 118c466f99d8b8ebada14c2d30f408ad00912b4f Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Mon, 6 Feb 2023 16:28:21 +0000 Subject: [PATCH 2/4] Update other crates --- p256/src/arithmetic.rs | 4 ++-- p384/src/arithmetic.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/p256/src/arithmetic.rs b/p256/src/arithmetic.rs index b48468c58..7cdf8b1dd 100644 --- a/p256/src/arithmetic.rs +++ b/p256/src/arithmetic.rs @@ -13,7 +13,7 @@ pub(crate) mod util; use self::{field::FieldElement, scalar::Scalar}; use crate::NistP256; use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; -use primeorder::{equation_a, PrimeCurveParams}; +use primeorder::{point_arithmetic, PrimeCurveParams}; /// Elliptic curve point in affine coordinates. pub type AffinePoint = primeorder::AffinePoint; @@ -36,7 +36,7 @@ impl PrimeCurveArithmetic for NistP256 { /// [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final impl PrimeCurveParams for NistP256 { type FieldElement = FieldElement; - type EquationAProperties = equation_a::IsMinusThree; + type PointArithmetic = point_arithmetic::EquationAIsMinusThree; /// a = -3 const EQUATION_A: FieldElement = FieldElement::from_u64(3).neg(); diff --git a/p384/src/arithmetic.rs b/p384/src/arithmetic.rs index cad5df95c..09163d445 100644 --- a/p384/src/arithmetic.rs +++ b/p384/src/arithmetic.rs @@ -15,7 +15,7 @@ pub(crate) mod scalar; use self::{field::FieldElement, scalar::Scalar}; use crate::NistP384; use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; -use primeorder::{equation_a, PrimeCurveParams}; +use primeorder::{point_arithmetic, PrimeCurveParams}; /// Elliptic curve point in affine coordinates. pub type AffinePoint = primeorder::AffinePoint; @@ -38,7 +38,7 @@ impl PrimeCurveArithmetic for NistP384 { /// [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final impl PrimeCurveParams for NistP384 { type FieldElement = FieldElement; - type EquationAProperties = equation_a::IsMinusThree; + type PointArithmetic = point_arithmetic::EquationAIsMinusThree; /// a = -3 (0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc) const EQUATION_A: FieldElement = FieldElement::from_u64(3).neg(); From 97908f4c18e6bf31436609b5b1fb03b25d37a67d Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Mon, 6 Feb 2023 16:39:41 +0000 Subject: [PATCH 3/4] Fix clippy warnings --- primeorder/src/point_arithmetic.rs | 312 ++++++++++++++--------------- 1 file changed, 156 insertions(+), 156 deletions(-) diff --git a/primeorder/src/point_arithmetic.rs b/primeorder/src/point_arithmetic.rs index 0faad6eff..0f74299a4 100644 --- a/primeorder/src/point_arithmetic.rs +++ b/primeorder/src/point_arithmetic.rs @@ -57,25 +57,25 @@ impl PointArithmetic for EquationAIsMinusThree { let xx = point.x.square(); // 1 let yy = point.y.square(); // 2 let zz = point.z.square(); // 3 - let xy2 = (point.x * &point.y).double(); // 4, 5 - let xz2 = (point.x * &point.z).double(); // 6, 7 - - let bzz_part = (C::EQUATION_B * &zz) - &xz2; // 8, 9 - let bzz3_part = bzz_part.double() + &bzz_part; // 10, 11 - let yy_m_bzz3 = yy - &bzz3_part; // 12 - let yy_p_bzz3 = yy + &bzz3_part; // 13 - let y_frag = yy_p_bzz3 * &yy_m_bzz3; // 14 - let x_frag = yy_m_bzz3 * &xy2; // 15 - - let zz3 = zz.double() + &zz; // 16, 17 - let bxz2_part = (C::EQUATION_B * &xz2) - &(zz3 + &xx); // 18, 19, 20 - let bxz6_part = bxz2_part.double() + &bxz2_part; // 21, 22 - let xx3_m_zz3 = xx.double() + &xx - &zz3; // 23, 24, 25 - - let y = y_frag + &(xx3_m_zz3 * &bxz6_part); // 26, 27 - let yz2 = (point.y * &point.z).double(); // 28, 29 - let x = x_frag - &(bxz6_part * &yz2); // 30, 31 - let z = (yz2 * &yy).double().double(); // 32, 33, 34 + let xy2 = (point.x * point.y).double(); // 4, 5 + let xz2 = (point.x * point.z).double(); // 6, 7 + + let bzz_part = (C::EQUATION_B * zz) - xz2; // 8, 9 + let bzz3_part = bzz_part.double() + bzz_part; // 10, 11 + let yy_m_bzz3 = yy - bzz3_part; // 12 + let yy_p_bzz3 = yy + bzz3_part; // 13 + let y_frag = yy_p_bzz3 * yy_m_bzz3; // 14 + let x_frag = yy_m_bzz3 * xy2; // 15 + + let zz3 = zz.double() + zz; // 16, 17 + let bxz2_part = (C::EQUATION_B * xz2) - (zz3 + xx); // 18, 19, 20 + let bxz6_part = bxz2_part.double() + bxz2_part; // 21, 22 + let xx3_m_zz3 = xx.double() + xx - zz3; // 23, 24, 25 + + let y = y_frag + (xx3_m_zz3 * bxz6_part); // 26, 27 + let yz2 = (point.y * point.z).double(); // 28, 29 + let x = x_frag - (bxz6_part * yz2); // 30, 31 + let z = (yz2 * yy).double().double(); // 32, 33, 34 ProjectivePoint { x, y, z } } @@ -94,27 +94,27 @@ impl PointArithmetic for EquationAIsMinusThree { "this implementation is only valid for C::EQUATION_A = -3" ); - let xx = lhs.x * &rhs.x; // 1 - let yy = lhs.y * &rhs.y; // 2 - let zz = lhs.z * &rhs.z; // 3 - let xy_pairs = ((lhs.x + &lhs.y) * &(rhs.x + &rhs.y)) - &(xx + &yy); // 4, 5, 6, 7, 8 - let yz_pairs = ((lhs.y + &lhs.z) * &(rhs.y + &rhs.z)) - &(yy + &zz); // 9, 10, 11, 12, 13 - let xz_pairs = ((lhs.x + &lhs.z) * &(rhs.x + &rhs.z)) - &(xx + &zz); // 14, 15, 16, 17, 18 + let xx = lhs.x * rhs.x; // 1 + let yy = lhs.y * rhs.y; // 2 + let zz = lhs.z * rhs.z; // 3 + let xy_pairs = ((lhs.x + lhs.y) * (rhs.x + rhs.y)) - (xx + yy); // 4, 5, 6, 7, 8 + let yz_pairs = ((lhs.y + lhs.z) * (rhs.y + rhs.z)) - (yy + zz); // 9, 10, 11, 12, 13 + let xz_pairs = ((lhs.x + lhs.z) * (rhs.x + rhs.z)) - (xx + zz); // 14, 15, 16, 17, 18 - let bzz_part = xz_pairs - &(C::EQUATION_B * &zz); // 19, 20 - let bzz3_part = bzz_part.double() + &bzz_part; // 21, 22 - let yy_m_bzz3 = yy - &bzz3_part; // 23 - let yy_p_bzz3 = yy + &bzz3_part; // 24 + let bzz_part = xz_pairs - (C::EQUATION_B * zz); // 19, 20 + let bzz3_part = bzz_part.double() + bzz_part; // 21, 22 + let yy_m_bzz3 = yy - bzz3_part; // 23 + let yy_p_bzz3 = yy + bzz3_part; // 24 - let zz3 = zz.double() + &zz; // 26, 27 - let bxz_part = (C::EQUATION_B * &xz_pairs) - &(zz3 + &xx); // 25, 28, 29 - let bxz3_part = bxz_part.double() + &bxz_part; // 30, 31 - let xx3_m_zz3 = xx.double() + &xx - &zz3; // 32, 33, 34 + let zz3 = zz.double() + zz; // 26, 27 + let bxz_part = (C::EQUATION_B * xz_pairs) - (zz3 + xx); // 25, 28, 29 + let bxz3_part = bxz_part.double() + bxz_part; // 30, 31 + let xx3_m_zz3 = xx.double() + xx - zz3; // 32, 33, 34 ProjectivePoint { - x: (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 35, 39, 40 - y: (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 36, 37, 38 - z: (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 41, 42, 43 + x: (yy_p_bzz3 * xy_pairs) - (yz_pairs * bxz3_part), // 35, 39, 40 + y: (yy_p_bzz3 * yy_m_bzz3) + (xx3_m_zz3 * bxz3_part), // 36, 37, 38 + z: (yy_m_bzz3 * yz_pairs) + (xy_pairs * xx3_m_zz3), // 41, 42, 43 } } @@ -132,26 +132,26 @@ impl PointArithmetic for EquationAIsMinusThree { "this implementation is only valid for C::EQUATION_A = -3" ); - let xx = lhs.x * &rhs.x; // 1 - let yy = lhs.y * &rhs.y; // 2 - let xy_pairs = ((lhs.x + &lhs.y) * &(rhs.x + &rhs.y)) - &(xx + &yy); // 3, 4, 5, 6, 7 - let yz_pairs = (rhs.y * &lhs.z) + &lhs.y; // 8, 9 (t4) - let xz_pairs = (rhs.x * &lhs.z) + &lhs.x; // 10, 11 (y3) + let xx = lhs.x * rhs.x; // 1 + let yy = lhs.y * rhs.y; // 2 + let xy_pairs = ((lhs.x + lhs.y) * (rhs.x + rhs.y)) - (xx + yy); // 3, 4, 5, 6, 7 + let yz_pairs = (rhs.y * lhs.z) + lhs.y; // 8, 9 (t4) + let xz_pairs = (rhs.x * lhs.z) + lhs.x; // 10, 11 (y3) - let bz_part = xz_pairs - &(C::EQUATION_B * &lhs.z); // 12, 13 - let bz3_part = bz_part.double() + &bz_part; // 14, 15 - let yy_m_bzz3 = yy - &bz3_part; // 16 - let yy_p_bzz3 = yy + &bz3_part; // 17 + let bz_part = xz_pairs - (C::EQUATION_B * lhs.z); // 12, 13 + let bz3_part = bz_part.double() + bz_part; // 14, 15 + let yy_m_bzz3 = yy - bz3_part; // 16 + let yy_p_bzz3 = yy + bz3_part; // 17 - let z3 = lhs.z.double() + &lhs.z; // 19, 20 - let bxz_part = (C::EQUATION_B * &xz_pairs) - &(z3 + &xx); // 18, 21, 22 - let bxz3_part = bxz_part.double() + &bxz_part; // 23, 24 - let xx3_m_zz3 = xx.double() + &xx - &z3; // 25, 26, 27 + let z3 = lhs.z.double() + lhs.z; // 19, 20 + let bxz_part = (C::EQUATION_B * xz_pairs) - (z3 + xx); // 18, 21, 22 + let bxz3_part = bxz_part.double() + bxz_part; // 23, 24 + let xx3_m_zz3 = xx.double() + xx - z3; // 25, 26, 27 let mut ret = ProjectivePoint { - x: (yy_p_bzz3 * &xy_pairs) - &(yz_pairs * &bxz3_part), // 28, 32, 33 - y: (yy_p_bzz3 * &yy_m_bzz3) + &(xx3_m_zz3 * &bxz3_part), // 29, 30, 31 - z: (yy_m_bzz3 * &yz_pairs) + &(xy_pairs * &xx3_m_zz3), // 34, 35, 36 + x: (yy_p_bzz3 * xy_pairs) - (yz_pairs * bxz3_part), // 28, 32, 33 + y: (yy_p_bzz3 * yy_m_bzz3) + (xx3_m_zz3 * bxz3_part), // 29, 30, 31 + z: (yy_m_bzz3 * yz_pairs) + (xy_pairs * xx3_m_zz3), // 34, 35, 36 }; ret.conditional_assign(lhs, rhs.is_identity()); ret @@ -175,37 +175,37 @@ impl PointArithmetic for EquationAIsGeneric { fn double(point: &ProjectivePoint) -> ProjectivePoint { let b3 = C::EQUATION_B * C::FieldElement::from(3); - let t0 = point.x * &point.x; // 1 - let t1 = point.y * &point.y; // 2 - let t2 = point.z * &point.z; // 3 - let t3 = point.x * &point.y; // 4 - let t3 = t3 + &t3; // 5 - let z3 = point.x * &point.z; // 6 - let z3 = z3 + &z3; // 7 - let x3 = C::EQUATION_A * &z3; // 8 - let y3 = b3 * &t2; // 9 - let y3 = x3 + &y3; // 10 - let x3 = t1 - &y3; // 11 - let y3 = t1 + &y3; // 12 - let y3 = x3 * &y3; // 13 - let x3 = t3 * &x3; // 14 - let z3 = b3 * &z3; // 15 - let t2 = C::EQUATION_A * &t2; // 16 - let t3 = t0 - &t2; // 17 - let t3 = C::EQUATION_A * &t3; // 18 - let t3 = t3 + &z3; // 19 - let z3 = t0 + &t0; // 20 - let t0 = z3 + &t0; // 21 - let t0 = t0 + &t2; // 22 - let t0 = t0 * &t3; // 23 - let y3 = y3 + &t0; // 24 - let t2 = point.y * &point.z; // 25 - let t2 = t2 + &t2; // 26 - let t0 = t2 * &t3; // 27 - let x3 = x3 - &t0; // 28 - let z3 = t2 * &t1; // 29 - let z3 = z3 + &z3; // 30 - let z3 = z3 + &z3; // 31 + let t0 = point.x * point.x; // 1 + let t1 = point.y * point.y; // 2 + let t2 = point.z * point.z; // 3 + let t3 = point.x * point.y; // 4 + let t3 = t3 + t3; // 5 + let z3 = point.x * point.z; // 6 + let z3 = z3 + z3; // 7 + let x3 = C::EQUATION_A * z3; // 8 + let y3 = b3 * t2; // 9 + let y3 = x3 + y3; // 10 + let x3 = t1 - y3; // 11 + let y3 = t1 + y3; // 12 + let y3 = x3 * y3; // 13 + let x3 = t3 * x3; // 14 + let z3 = b3 * z3; // 15 + let t2 = C::EQUATION_A * t2; // 16 + let t3 = t0 - t2; // 17 + let t3 = C::EQUATION_A * t3; // 18 + let t3 = t3 + z3; // 19 + let z3 = t0 + t0; // 20 + let t0 = z3 + t0; // 21 + let t0 = t0 + t2; // 22 + let t0 = t0 * t3; // 23 + let y3 = y3 + t0; // 24 + let t2 = point.y * point.z; // 25 + let t2 = t2 + t2; // 26 + let t0 = t2 * t3; // 27 + let x3 = x3 - t0; // 28 + let z3 = t2 * t1; // 29 + let z3 = z3 + z3; // 30 + let z3 = z3 + z3; // 31 ProjectivePoint { x: x3, @@ -224,46 +224,46 @@ impl PointArithmetic for EquationAIsGeneric { fn add(lhs: &ProjectivePoint, rhs: &ProjectivePoint) -> ProjectivePoint { let b3 = C::FieldElement::from(3) * C::EQUATION_B; - let t0 = lhs.x * &rhs.x; // 1 - let t1 = lhs.y * &rhs.y; // 2 - let t2 = lhs.z * &rhs.z; // 3 - let t3 = lhs.x + &lhs.y; // 4 - let t4 = rhs.x + &rhs.y; // 5 - let t3 = t3 * &t4; // 6 - let t4 = t0 + &t1; // 7 - let t3 = t3 - &t4; // 8 - let t4 = lhs.x + &lhs.z; // 9 - let t5 = rhs.x + &rhs.z; // 10 - let t4 = t4 * &t5; // 11 - let t5 = t0 + &t2; // 12 - let t4 = t4 - &t5; // 13 - let t5 = lhs.y + &lhs.z; // 14 - let x3 = rhs.y + &rhs.z; // 15 - let t5 = t5 * &x3; // 16 - let x3 = t1 + &t2; // 17 - let t5 = t5 - &x3; // 18 - let z3 = C::EQUATION_A * &t4; // 19 - let x3 = b3 * &t2; // 20 - let z3 = x3 + &z3; // 21 - let x3 = t1 - &z3; // 22 - let z3 = t1 + &z3; // 23 - let y3 = x3 * &z3; // 24 - let t1 = t0 + &t0; // 25 - let t1 = t1 + &t0; // 26 - let t2 = C::EQUATION_A * &t2; // 27 - let t4 = b3 * &t4; // 28 - let t1 = t1 + &t2; // 29 - let t2 = t0 - &t2; // 30 - let t2 = C::EQUATION_A * &t2; // 31 - let t4 = t4 + &t2; // 32 - let t0 = t1 * &t4; // 33 - let y3 = y3 + &t0; // 34 - let t0 = t5 * &t4; // 35 - let x3 = t3 * &x3; // 36 - let x3 = x3 - &t0; // 37 - let t0 = t3 * &t1; // 38 - let z3 = t5 * &z3; // 39 - let z3 = z3 + &t0; // 40 + let t0 = lhs.x * rhs.x; // 1 + let t1 = lhs.y * rhs.y; // 2 + let t2 = lhs.z * rhs.z; // 3 + let t3 = lhs.x + lhs.y; // 4 + let t4 = rhs.x + rhs.y; // 5 + let t3 = t3 * t4; // 6 + let t4 = t0 + t1; // 7 + let t3 = t3 - t4; // 8 + let t4 = lhs.x + lhs.z; // 9 + let t5 = rhs.x + rhs.z; // 10 + let t4 = t4 * t5; // 11 + let t5 = t0 + t2; // 12 + let t4 = t4 - t5; // 13 + let t5 = lhs.y + lhs.z; // 14 + let x3 = rhs.y + rhs.z; // 15 + let t5 = t5 * x3; // 16 + let x3 = t1 + t2; // 17 + let t5 = t5 - x3; // 18 + let z3 = C::EQUATION_A * t4; // 19 + let x3 = b3 * t2; // 20 + let z3 = x3 + z3; // 21 + let x3 = t1 - z3; // 22 + let z3 = t1 + z3; // 23 + let y3 = x3 * z3; // 24 + let t1 = t0 + t0; // 25 + let t1 = t1 + t0; // 26 + let t2 = C::EQUATION_A * t2; // 27 + let t4 = b3 * t4; // 28 + let t1 = t1 + t2; // 29 + let t2 = t0 - t2; // 30 + let t2 = C::EQUATION_A * t2; // 31 + let t4 = t4 + t2; // 32 + let t0 = t1 * t4; // 33 + let y3 = y3 + t0; // 34 + let t0 = t5 * t4; // 35 + let x3 = t3 * x3; // 36 + let x3 = x3 - t0; // 37 + let t0 = t3 * t1; // 38 + let z3 = t5 * z3; // 39 + let z3 = z3 + t0; // 40 ProjectivePoint { x: x3, @@ -282,39 +282,39 @@ impl PointArithmetic for EquationAIsGeneric { fn add_mixed(lhs: &ProjectivePoint, rhs: &AffinePoint) -> ProjectivePoint { let b3 = C::EQUATION_B * C::FieldElement::from(3); - let t0 = lhs.x * &rhs.x; // 1 - let t1 = lhs.y * &rhs.y; // 2 - let t3 = rhs.x + &rhs.y; // 3 - let t4 = lhs.x + &lhs.y; // 4 - let t3 = t3 * &t4; // 5 - let t4 = t0 + &t1; // 6 - let t3 = t3 - &t4; // 7 - let t4 = rhs.x * &lhs.z; // 8 - let t4 = t4 + &lhs.x; // 9 - let t5 = rhs.y * &lhs.z; // 10 - let t5 = t5 + &lhs.y; // 11 - let z3 = C::EQUATION_A * &t4; // 12 - let x3 = b3 * &lhs.z; // 13 - let z3 = x3 + &z3; // 14 - let x3 = t1 - &z3; // 15 - let z3 = t1 + &z3; // 16 - let y3 = x3 * &z3; // 17 - let t1 = t0 + &t0; // 18 - let t1 = t1 + &t0; // 19 - let t2 = C::EQUATION_A * &lhs.z; // 20 - let t4 = b3 * &t4; // 21 - let t1 = t1 + &t2; // 22 - let t2 = t0 - &t2; // 23 - let t2 = C::EQUATION_A * &t2; // 24 - let t4 = t4 + &t2; // 25 - let t0 = t1 * &t4; // 26 - let y3 = y3 + &t0; // 27 - let t0 = t5 * &t4; // 28 - let x3 = t3 * &x3; // 29 - let x3 = x3 - &t0; // 30 - let t0 = t3 * &t1; // 31 - let z3 = t5 * &z3; // 32 - let z3 = z3 + &t0; // 33 + let t0 = lhs.x * rhs.x; // 1 + let t1 = lhs.y * rhs.y; // 2 + let t3 = rhs.x + rhs.y; // 3 + let t4 = lhs.x + lhs.y; // 4 + let t3 = t3 * t4; // 5 + let t4 = t0 + t1; // 6 + let t3 = t3 - t4; // 7 + let t4 = rhs.x * lhs.z; // 8 + let t4 = t4 + lhs.x; // 9 + let t5 = rhs.y * lhs.z; // 10 + let t5 = t5 + lhs.y; // 11 + let z3 = C::EQUATION_A * t4; // 12 + let x3 = b3 * lhs.z; // 13 + let z3 = x3 + z3; // 14 + let x3 = t1 - z3; // 15 + let z3 = t1 + z3; // 16 + let y3 = x3 * z3; // 17 + let t1 = t0 + t0; // 18 + let t1 = t1 + t0; // 19 + let t2 = C::EQUATION_A * lhs.z; // 20 + let t4 = b3 * t4; // 21 + let t1 = t1 + t2; // 22 + let t2 = t0 - t2; // 23 + let t2 = C::EQUATION_A * t2; // 24 + let t4 = t4 + t2; // 25 + let t0 = t1 * t4; // 26 + let y3 = y3 + t0; // 27 + let t0 = t5 * t4; // 28 + let x3 = t3 * x3; // 29 + let x3 = x3 - t0; // 30 + let t0 = t3 * t1; // 31 + let z3 = t5 * z3; // 32 + let z3 = z3 + t0; // 33 let mut ret = ProjectivePoint { x: x3, From 0cb24bbc93a1267174c905954b5099df3b54a85e Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Mon, 6 Feb 2023 18:25:35 +0000 Subject: [PATCH 4/4] Hide PointArithmetic trait --- primeorder/src/point_arithmetic.rs | 34 ++++++++++++++---------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/primeorder/src/point_arithmetic.rs b/primeorder/src/point_arithmetic.rs index 0f74299a4..ca3e9f88b 100644 --- a/primeorder/src/point_arithmetic.rs +++ b/primeorder/src/point_arithmetic.rs @@ -17,28 +17,28 @@ use elliptic_curve::{subtle::ConditionallySelectable, Field}; use crate::{AffinePoint, PrimeCurveParams, ProjectivePoint}; mod sealed { - /// Seals `PointArithmetic` trait - pub trait Sealed {} -} + use crate::{AffinePoint, PrimeCurveParams, ProjectivePoint}; -/// Elliptic point artihmetic implementation -/// -/// Provides implementation of point arithmetic (point addition, point doubling) which -/// might be optimized for the curve. -pub trait PointArithmetic: sealed::Sealed { - /// Returns `point + point` - fn double(point: &ProjectivePoint) -> ProjectivePoint; - /// Returns `lhs + rhs` - fn add(lhs: &ProjectivePoint, rhs: &ProjectivePoint) -> ProjectivePoint; - /// Returns `lhs + rhs` - fn add_mixed(lhs: &ProjectivePoint, rhs: &AffinePoint) -> ProjectivePoint; + /// Elliptic point artihmetic implementation + /// + /// Provides implementation of point arithmetic (point addition, point doubling) which + /// might be optimized for the curve. + pub trait PointArithmetic { + /// Returns `point + point` + fn double(point: &ProjectivePoint) -> ProjectivePoint; + /// Returns `lhs + rhs` + fn add(lhs: &ProjectivePoint, rhs: &ProjectivePoint) -> ProjectivePoint; + /// Returns `lhs + rhs` + fn add_mixed(lhs: &ProjectivePoint, rhs: &AffinePoint) -> ProjectivePoint; + } } +/// Allow crate-local visibility +pub(crate) use sealed::PointArithmetic; + /// The 𝒂-coefficient of the short Weierstrass equation is -3. pub struct EquationAIsMinusThree {} -impl sealed::Sealed for EquationAIsMinusThree {} - impl PointArithmetic for EquationAIsMinusThree { /// Implements point doubling for curves with `a = -3` /// @@ -162,8 +162,6 @@ impl PointArithmetic for EquationAIsMinusThree { /// properties which allow for an optimized implementation. pub struct EquationAIsGeneric {} -impl sealed::Sealed for EquationAIsGeneric {} - impl PointArithmetic for EquationAIsGeneric { /// Implements point doubling for curves with any `a` ///