Skip to content

Commit

Permalink
primeorder
Browse files Browse the repository at this point in the history
  • Loading branch information
ycscaly committed Nov 13, 2023
1 parent cbf269b commit d6069fe
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 54 deletions.
10 changes: 1 addition & 9 deletions bign256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use core::{
use elliptic_curve::{
bigint::Limb,
ff::PrimeField,
ops::{Invert, Reduce},
ops::Reduce,
scalar::{FromUintUnchecked, IsHigh},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption},
Curve as _, Error, Result, ScalarPrimitive,
Expand Down Expand Up @@ -144,14 +144,6 @@ impl FromUintUnchecked for Scalar {
}
}

impl Invert for Scalar {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
const MODULUS_SHR1: U256 = BignP256::ORDER.shr_vartime(1);
Expand Down
10 changes: 1 addition & 9 deletions p192/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use core::{
use elliptic_curve::{
bigint::Limb,
ff::PrimeField,
ops::{Invert, Reduce},
ops::Reduce,
scalar::{FromUintUnchecked, IsHigh},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption},
Curve as _, Error, Result, ScalarPrimitive,
Expand Down Expand Up @@ -182,14 +182,6 @@ impl FromUintUnchecked for Scalar {
}
}

impl Invert for Scalar {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
const MODULUS_SHR1: U192 = NistP192::ORDER.shr_vartime(1);
Expand Down
10 changes: 1 addition & 9 deletions p224/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use core::{
use elliptic_curve::{
bigint::Limb,
ff::PrimeField,
ops::{Invert, Reduce},
ops::Reduce,
scalar::{FromUintUnchecked, IsHigh},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption},
Curve as _, Error, Result, ScalarPrimitive,
Expand Down Expand Up @@ -166,14 +166,6 @@ impl FromUintUnchecked for Scalar {
}
}

impl Invert for Scalar {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
const MODULUS_SHR1: Uint = NistP224::ORDER.shr_vartime(1);
Expand Down
9 changes: 9 additions & 0 deletions p256/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use core::{
iter::{Product, Sum},
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use elliptic_curve::ops::Invert;
use elliptic_curve::{
bigint::{ArrayEncoding, U256},
ff::{Field, PrimeField},
Expand Down Expand Up @@ -507,6 +508,14 @@ impl PartialEq for FieldElement {
}
}

impl Invert for FieldElement {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

impl Add<FieldElement> for FieldElement {
type Output = FieldElement;

Expand Down
10 changes: 1 addition & 9 deletions p384/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use core::{
use elliptic_curve::{
bigint::{ArrayEncoding, Limb},
ff::PrimeField,
ops::{Invert, Reduce},
ops::Reduce,
scalar::{FromUintUnchecked, IsHigh},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption},
Curve as _, Error, Result, ScalarPrimitive,
Expand Down Expand Up @@ -196,14 +196,6 @@ impl FromUintUnchecked for Scalar {
}
}

impl Invert for Scalar {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
const MODULUS_SHR1: U384 = NistP384::ORDER.shr_vartime(1);
Expand Down
9 changes: 9 additions & 0 deletions p521/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use core::{
iter::{Product, Sum},
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use elliptic_curve::ops::Invert;
use elliptic_curve::{
ff::{self, Field, PrimeField},
generic_array::GenericArray,
Expand Down Expand Up @@ -625,6 +626,14 @@ impl<'a> Product<&'a FieldElement> for FieldElement {
}
}

impl Invert for FieldElement {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

#[cfg(test)]
mod tests {
use super::FieldElement;
Expand Down
8 changes: 8 additions & 0 deletions primeorder/src/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,14 @@ macro_rules! impl_mont_field_element_arithmetic {
}
}

impl $crate::elliptic_curve::ops::Invert for $fe {
type Output = $crate::elliptic_curve::subtle::CtOption<Self>;

fn invert(&self) -> $crate::elliptic_curve::subtle::CtOption<Self> {
self.invert()
}
}

impl $crate::elliptic_curve::subtle::ConditionallySelectable for $fe {
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
Self(<$uint>::conditional_select(&a.0, &b.0, choice))
Expand Down
5 changes: 4 additions & 1 deletion primeorder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub use elliptic_curve::{
self, generic_array, point::Double, Field, FieldBytes, PrimeCurve, PrimeField,
};

use elliptic_curve::ops::Invert;
use elliptic_curve::subtle::CtOption;
use elliptic_curve::CurveArithmetic;

/// Parameters for elliptic curves of prime order which can be described by the
Expand All @@ -32,7 +34,8 @@ pub trait PrimeCurveParams:
+ CurveArithmetic<ProjectivePoint = ProjectivePoint<Self>>
{
/// Base field element type.
type FieldElement: PrimeField<Repr = FieldBytes<Self>>;
type FieldElement: PrimeField<Repr = FieldBytes<Self>>
+ Invert<Output = CtOption<Self::FieldElement>>;

/// [Point arithmetic](point_arithmetic) implementation, might be optimized for this specific curve
type PointArithmetic: point_arithmetic::PointArithmetic<Self>;
Expand Down
98 changes: 90 additions & 8 deletions primeorder/src/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use core::{
iter::Sum,
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use elliptic_curve::ops::Invert;
use elliptic_curve::{
bigint::{ArrayEncoding, Integer},
generic_array::ArrayLength,
Expand All @@ -26,7 +27,7 @@ use elliptic_curve::{
},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
zeroize::DefaultIsZeroes,
Error, FieldBytes, FieldBytesSize, PublicKey, Result, Scalar,
Error, FieldBytes, FieldBytesSize, Normalize, PublicKey, Result, Scalar,
};

/// Point on a Weierstrass curve in projective coordinates.
Expand Down Expand Up @@ -57,16 +58,19 @@ where

/// Returns the affine representation of this point, or `None` if it is the identity.
pub fn to_affine(&self) -> AffinePoint<C> {
self.z
.invert()
.map(|zinv| AffinePoint {
x: self.x * &zinv,
y: self.y * &zinv,
infinity: 0,
})
<C::FieldElement as Field>::invert(&self.z)
.map(|zinv| self.to_affine_internal(zinv))
.unwrap_or(AffinePoint::IDENTITY)
}

pub(super) fn to_affine_internal(&self, zinv: C::FieldElement) -> AffinePoint<C> {
AffinePoint {
x: self.x * &zinv,
y: self.y * &zinv,
infinity: 0,
}
}

/// Returns `-self`.
pub fn neg(&self) -> Self {
Self {
Expand Down Expand Up @@ -326,6 +330,84 @@ where
fn to_affine(&self) -> AffinePoint<C> {
ProjectivePoint::to_affine(self)
}

#[cfg(feature = "alloc")]
fn batch_normalize(p: &[Self], q: &mut [Self::AffineRepr]) {
assert_eq!(p.len(), q.len());

let affine_points: alloc::vec::Vec<_> = <Self as Normalize>::batch_normalize_slice(p);
for i in 0..q.len() {
q[i] = affine_points[i];
}
}
}

impl<C> Normalize for ProjectivePoint<C>
where
Self: Double,
C: PrimeCurveParams,
{
fn batch_normalize_array<const N: usize>(points: &[Self; N]) -> [Self::AffineRepr; N] {
let mut zs = [C::FieldElement::ONE; N];

for i in 0..N {
if points[i].z != C::FieldElement::ZERO {
// Even a single zero value will fail inversion for the entire batch.
// Put a dummy value (above `FieldElement::ONE`) so inversion succeeds
// and treat that case specially later-on.
zs[i] = points[i].z;
}
}

// This is safe to unwrap since we assured that all elements are non-zero
let zs_inverses = <C::FieldElement as Invert>::batch_invert_array(&zs).unwrap();

let mut affine_points = [AffinePoint::IDENTITY; N];
for i in 0..N {
if points[i].z != C::FieldElement::ZERO {
// If the `z` coordinate is non-zero, we can use it to invert;
// otherwise it defaults to the `IDENTITY` value in initialization.
affine_points[i] = points[i].to_affine_internal(zs_inverses[i])
}
}

affine_points
}

#[cfg(not(feature = "alloc"))]
fn batch_normalize_slice<B: FromIterator<Self::AffineRepr>>(_points: &[Self]) -> B {
todo!()
}

#[cfg(feature = "alloc")]
fn batch_normalize_slice<B: FromIterator<Self::AffineRepr>>(points: &[Self]) -> B {
let mut zs: alloc::vec::Vec<_> = (0..points.len()).map(|_| C::FieldElement::ONE).collect();

for i in 0..points.len() {
if points[i].z != C::FieldElement::ZERO {
// Even a single zero value will fail inversion for the entire batch.
// Put a dummy value (above `C::FieldElement::ONE`) so inversion succeeds
// and treat that case specially later-on.
zs[i] = points[i].z;
}
}

// This is safe to unwrap since we assured that all elements are non-zero
let zs_inverses: alloc::vec::Vec<_> =
<C::FieldElement as Invert>::batch_invert_slice(zs.as_slice()).unwrap();

let mut affine_points: alloc::vec::Vec<_> =
(0..points.len()).map(|_| AffinePoint::IDENTITY).collect();
for i in 0..points.len() {
if points[i].z != C::FieldElement::ZERO {
// If the `z` coordinate is non-zero, we can use it to invert;
// otherwise it defaults to the `IDENTITY` value in initialization.
affine_points[i] = points[i].to_affine_internal(zs_inverses[i])
}
}

affine_points.into_iter().collect()
}
}

impl<C> LinearCombination for ProjectivePoint<C>
Expand Down
10 changes: 1 addition & 9 deletions sm2/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use core::{
use elliptic_curve::{
bigint::Limb,
ff::PrimeField,
ops::{Invert, Reduce},
ops::Reduce,
scalar::{FromUintUnchecked, IsHigh},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption},
Curve as _, Error, Result, ScalarPrimitive,
Expand Down Expand Up @@ -161,14 +161,6 @@ impl FromUintUnchecked for Scalar {
}
}

impl Invert for Scalar {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
const MODULUS_SHR1: U256 = Sm2::ORDER.shr_vartime(1);
Expand Down

0 comments on commit d6069fe

Please sign in to comment.