diff --git a/CHANGELOG.md b/CHANGELOG.md index 70542b7..6898c8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,13 +7,17 @@ and this project adheres to Rust's notion of ## [Unreleased] +## [0.2.0] - 2021-09-02 +### Changed +- Migrated to `ff 0.11`, `group 0.11`. + ## [0.1.2] - 2021-08-06 -## Added +### Added - Implementation of `group::WnafGroup` for Pallas and Vesta, enabling them to be used with `group::Wnaf` for targeted performance improvements. ## [0.1.1] - 2021-06-04 -## Added +### Added - Implementations of `group::cofactor::{CofactorCurve, CofactorCurveAffine}` for Pallas and Vesta, enabling them to be used in cofactor-aware protocols that also want to leverage the affine point representation. diff --git a/Cargo.toml b/Cargo.toml index 4147bbc..84ae0ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pasta_curves" description = "Implementation of the Pallas and Vesta (Pasta) curve cycle" -version = "0.1.2" +version = "0.2.0" authors = [ "Sean Bowe ", "Ying Tong Lai ", @@ -41,8 +41,8 @@ harness = false [dependencies] subtle = "2.3" -ff = "0.10" -group = "0.10" +ff = "0.11" +group = "0.11" rand = "0.8" blake2b_simd = "0.5" lazy_static = "1.4.0" diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index 2d774f6..e9caea2 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -6,7 +6,7 @@ use static_assertions::const_assert; use std::assert; use std::convert::TryInto; use std::marker::PhantomData; -use subtle::{Choice, ConstantTimeEq, CtOption}; +use subtle::{Choice, CtOption}; use super::Group; @@ -16,9 +16,7 @@ const_assert!(size_of::() >= 4); /// This trait is a common interface for dealing with elements of a finite /// field. -pub trait FieldExt: - ff::PrimeField + From + Ord + ConstantTimeEq + Group -{ +pub trait FieldExt: ff::PrimeField + From + Ord + Group { /// Modulus of the field written as a string for display purposes const MODULUS: &'static str; @@ -69,9 +67,6 @@ pub trait FieldExt: Self::random(rand::rngs::OsRng) } - /// Returns whether or not this element is zero. - fn ct_is_zero(&self) -> Choice; - /// Obtains a field element congruent to the integer `v`. fn from_u64(v: u64) -> Self; @@ -133,31 +128,6 @@ pub trait FieldExt: fn pow_by_t_minus1_over2(&self) -> Self { ff::Field::pow_vartime(&self, &Self::T_MINUS1_OVER2) } - - /// Performs a batch inversion using Montgomery's trick, returns the product - /// of every inverse. Zero inputs are ignored. - fn batch_invert(v: &mut [Self]) -> Self { - let mut tmp = Vec::with_capacity(v.len()); - - let mut acc = Self::one(); - for p in v.iter() { - tmp.push(acc); - acc = Self::conditional_select(&(acc * p), &acc, p.ct_is_zero()); - } - - acc = acc.invert().unwrap(); - let allinv = acc; - - for (p, tmp) in v.iter_mut().rev().zip(tmp.into_iter().rev()) { - let skip = p.ct_is_zero(); - - let tmp = tmp * acc; - acc = Self::conditional_select(&(acc * *p), &acc, skip); - *p = Self::conditional_select(&tmp, p, skip); - } - - allinv - } } /// Parameters for a perfect hash function used in square root computation. @@ -296,10 +266,10 @@ impl SqrtTables { let res = self.sqrt_common(&uv, &v); let sqdiv = res.square() * div; - let is_square = (sqdiv - num).ct_is_zero(); - let is_nonsquare = (sqdiv - F::ROOT_OF_UNITY * num).ct_is_zero(); + let is_square = (sqdiv - num).is_zero(); + let is_nonsquare = (sqdiv - F::ROOT_OF_UNITY * num).is_zero(); assert!(bool::from( - num.ct_is_zero() | div.ct_is_zero() | (is_square ^ is_nonsquare) + num.is_zero() | div.is_zero() | (is_square ^ is_nonsquare) )); (is_square, res) @@ -313,9 +283,9 @@ impl SqrtTables { let res = self.sqrt_common(&uv, &v); let sq = res.square(); - let is_square = (sq - u).ct_is_zero(); - let is_nonsquare = (sq - F::ROOT_OF_UNITY * u).ct_is_zero(); - assert!(bool::from(u.ct_is_zero() | (is_square ^ is_nonsquare))); + let is_square = (sq - u).is_zero(); + let is_nonsquare = (sq - F::ROOT_OF_UNITY * u).is_zero(); + assert!(bool::from(u.is_zero() | (is_square ^ is_nonsquare))); (is_square, res) } diff --git a/src/curves.rs b/src/curves.rs index c9d954f..93778e2 100644 --- a/src/curves.rs +++ b/src/curves.rs @@ -92,7 +92,7 @@ macro_rules! new_curve_impl { } fn is_identity(&self) -> Choice { - self.z.ct_is_zero() + self.z.is_zero() } } @@ -150,7 +150,7 @@ macro_rules! new_curve_impl { let z6 = z4 * z2; (self.y.square() - (self.x.square() + $name::curve_constant_a() * z4) * self.x) .ct_eq(&(z6 * $name::curve_constant_b())) - | self.z.ct_is_zero() + | self.z.is_zero() } } @@ -208,7 +208,7 @@ macro_rules! new_curve_impl { infinity: Choice::from(0u8), }; - $name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.ct_is_zero()) + $name_affine::conditional_select(&tmp, &$name_affine::identity(), zinv.is_zero()) } } @@ -647,7 +647,7 @@ macro_rules! new_curve_impl { tmp[31] &= 0b0111_1111; $base::from_bytes(&tmp).and_then(|x| { - CtOption::new(Self::identity(), x.ct_is_zero() & (!ysign)).or_else(|| { + CtOption::new(Self::identity(), x.is_zero() & (!ysign)).or_else(|| { let x3 = x.square() * x; (x3 + $name::curve_constant_b()).sqrt().and_then(|y| { let sign = Choice::from(y.to_bytes()[0] & 1); diff --git a/src/fields/fp.rs b/src/fields/fp.rs index d72b0ee..eb943b0 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -480,10 +480,6 @@ impl ff::Field for Fp { Self::one() } - fn is_zero(&self) -> bool { - self.ct_is_zero().into() - } - fn double(&self) -> Self { self.double() } @@ -538,16 +534,16 @@ impl ff::PrimeField for Fp { const CAPACITY: u32 = 254; const S: u32 = S; - fn from_repr(repr: Self::Repr) -> Option { - Self::from_bytes(&repr).into() + fn from_repr(repr: Self::Repr) -> CtOption { + Self::from_bytes(&repr) } fn to_repr(&self) -> Self::Repr { self.to_bytes() } - fn is_odd(&self) -> bool { - self.to_bytes()[0] & 1 == 1 + fn is_odd(&self) -> Choice { + Choice::from(self.to_bytes()[0] & 1) } fn multiplicative_generator() -> Self { @@ -656,10 +652,6 @@ impl FieldExt for Fp { FP_TABLES.sqrt_alt(self) } - fn ct_is_zero(&self) -> Choice { - self.ct_eq(&Self::zero()) - } - fn from_u64(v: u64) -> Self { Fp::from_raw([v as u64, 0, 0, 0]) } diff --git a/src/fields/fq.rs b/src/fields/fq.rs index 3bf0b1f..b624a67 100644 --- a/src/fields/fq.rs +++ b/src/fields/fq.rs @@ -480,10 +480,6 @@ impl ff::Field for Fq { Self::one() } - fn is_zero(&self) -> bool { - self.ct_is_zero().into() - } - fn double(&self) -> Self { self.double() } @@ -538,16 +534,16 @@ impl ff::PrimeField for Fq { const CAPACITY: u32 = 254; const S: u32 = S; - fn from_repr(repr: Self::Repr) -> Option { - Self::from_bytes(&repr).into() + fn from_repr(repr: Self::Repr) -> CtOption { + Self::from_bytes(&repr) } fn to_repr(&self) -> Self::Repr { self.to_bytes() } - fn is_odd(&self) -> bool { - self.to_bytes()[0] & 1 == 1 + fn is_odd(&self) -> Choice { + Choice::from(self.to_bytes()[0] & 1) } fn multiplicative_generator() -> Self { @@ -656,10 +652,6 @@ impl FieldExt for Fq { FQ_TABLES.sqrt_alt(self) } - fn ct_is_zero(&self) -> Choice { - self.ct_eq(&Self::zero()) - } - fn from_u64(v: u64) -> Self { Fq::from_raw([v as u64, 0, 0, 0]) } diff --git a/src/hashtocurve.rs b/src/hashtocurve.rs index 2adc7da..e09f3e7 100644 --- a/src/hashtocurve.rs +++ b/src/hashtocurve.rs @@ -137,7 +137,7 @@ pub fn map_to_curve_simple_swu, I: CurveExt