diff --git a/bellman/src/domain.rs b/bellman/src/domain.rs index f1c2592..0e9192e 100644 --- a/bellman/src/domain.rs +++ b/bellman/src/domain.rs @@ -11,7 +11,7 @@ //! [`EvaluationDomain`]: crate::domain::EvaluationDomain //! [Groth16]: https://eprint.iacr.org/2016/260 -use ff::{Field, PowVartime, PrimeField, ScalarEngine}; +use ff::{Field, PrimeField, ScalarEngine}; use group::CurveProjective; use std::ops::{AddAssign, MulAssign, SubAssign}; diff --git a/bellman/src/gadgets/multieq.rs b/bellman/src/gadgets/multieq.rs index 890eb7c..37b2d94 100644 --- a/bellman/src/gadgets/multieq.rs +++ b/bellman/src/gadgets/multieq.rs @@ -1,4 +1,4 @@ -use ff::{PowVartime, PrimeField, ScalarEngine}; +use ff::{Field, PrimeField, ScalarEngine}; use crate::{ConstraintSystem, LinearCombination, SynthesisError, Variable}; diff --git a/bellman/src/gadgets/test/mod.rs b/bellman/src/gadgets/test/mod.rs index d09d87e..25f0c85 100644 --- a/bellman/src/gadgets/test/mod.rs +++ b/bellman/src/gadgets/test/mod.rs @@ -1,6 +1,6 @@ //! Helpers for testing circuit implementations. -use ff::{Endianness, Field, PowVartime, PrimeField, ScalarEngine}; +use ff::{Endianness, Field, PrimeField, ScalarEngine}; use crate::{ConstraintSystem, Index, LinearCombination, SynthesisError, Variable}; diff --git a/bellman/src/groth16/generator.rs b/bellman/src/groth16/generator.rs index 1d86992..02efc21 100644 --- a/bellman/src/groth16/generator.rs +++ b/bellman/src/groth16/generator.rs @@ -2,7 +2,7 @@ use rand_core::RngCore; use std::ops::{AddAssign, MulAssign}; use std::sync::Arc; -use ff::{Field, PowVartime}; +use ff::Field; use group::{CurveAffine, CurveProjective, Wnaf}; use pairing::Engine; diff --git a/bellman/src/groth16/tests/dummy_engine.rs b/bellman/src/groth16/tests/dummy_engine.rs index b738faf..14bd588 100644 --- a/bellman/src/groth16/tests/dummy_engine.rs +++ b/bellman/src/groth16/tests/dummy_engine.rs @@ -1,4 +1,4 @@ -use ff::{Field, PowVartime, PrimeField, ScalarEngine}; +use ff::{Field, PrimeField, ScalarEngine}; use group::{CurveAffine, CurveProjective, EncodedPoint, GroupDecodingError}; use pairing::{Engine, PairingCurveAffine}; diff --git a/bellman/src/groth16/tests/mod.rs b/bellman/src/groth16/tests/mod.rs index 2914bf2..276738c 100644 --- a/bellman/src/groth16/tests/mod.rs +++ b/bellman/src/groth16/tests/mod.rs @@ -1,4 +1,4 @@ -use ff::{Field, PowVartime, PrimeField}; +use ff::{Field, PrimeField}; use pairing::Engine; mod dummy_engine; diff --git a/ff/src/lib.rs b/ff/src/lib.rs index d59ebfe..2175de0 100644 --- a/ff/src/lib.rs +++ b/ff/src/lib.rs @@ -76,36 +76,21 @@ pub trait Field: /// Returns the square root of the field element, if it is /// quadratic residue. fn sqrt(&self) -> CtOption; -} - -pub trait PowVartime: Field -where - L: Copy + PartialEq + PartialOrd + AddAssign, - L: BitAnd, - L: Shr, - L: Sub, -{ - const ZERO: L; - const ONE: L; - const LIMB_SIZE: L; /// Exponentiates `self` by `exp`, where `exp` is a little-endian order /// integer exponent. /// /// **This operation is variable time with respect to the exponent.** If the /// exponent is fixed, this operation is effectively constant time. - fn pow_vartime>(&self, exp: S) -> Self { + fn pow_vartime>(&self, exp: S) -> Self { let mut res = Self::one(); for e in exp.as_ref().iter().rev() { - let mut i = Self::ZERO; - while i < Self::LIMB_SIZE { + for i in (0..64).rev() { res = res.square(); - if ((*e >> (Self::LIMB_SIZE - Self::ONE - i)) & Self::ONE) == Self::ONE { + if ((*e >> i) & 1) == 1 { res.mul_assign(self); } - - i += Self::ONE; } } @@ -113,18 +98,6 @@ where } } -impl PowVartime for T { - const ZERO: u8 = 0; - const ONE: u8 = 1; - const LIMB_SIZE: u8 = 8; -} - -impl PowVartime for T { - const ZERO: u64 = 0; - const ONE: u64 = 1; - const LIMB_SIZE: u64 = 64; -} - /// Helper trait for converting the binary representation of a prime field element into a /// specific endianness. This is useful when you need to act on the bit representation /// of an element generically, as the native binary representation of a prime field is diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index bc7abaf..4daf4bd 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/src/bls12_381/fq.rs @@ -2,8 +2,6 @@ use super::fq2::Fq2; use ff::{Field, PrimeField}; use std::ops::{AddAssign, MulAssign, SubAssign}; -#[cfg(test)] -use ff::PowVartime; #[cfg(test)] use std::ops::Neg; @@ -1644,11 +1642,15 @@ fn test_fq_pow() { assert_eq!(c, target); } + use byteorder::ByteOrder; + let mut char_limbs = [0; 6]; + byteorder::LittleEndian::read_u64_into(Fq::char().as_ref(), &mut char_limbs); + for _ in 0..1000 { // Exponentiating by the modulus should have no effect in a prime field. let a = Fq::random(&mut rng); - assert_eq!(a, a.pow_vartime(Fq::char())); + assert_eq!(a, a.pow_vartime(char_limbs)); } } diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index 473753e..38b48bc 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -1,5 +1,5 @@ use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE}; -use ff::{Field, PowVartime}; +use ff::Field; use rand_core::RngCore; use std::cmp::Ordering; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index e01978d..3e2e1f6 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -7,8 +7,6 @@ use std::ops::{AddAssign, MulAssign, SubAssign}; #[PrimeFieldReprEndianness = "little"] pub struct Fr([u64; 4]); -#[cfg(test)] -use ff::PowVartime; #[cfg(test)] use rand_core::SeedableRng; #[cfg(test)] @@ -430,11 +428,15 @@ fn test_fr_pow() { assert_eq!(c, target); } + use byteorder::ByteOrder; + let mut char_limbs = [0; 4]; + byteorder::LittleEndian::read_u64_into(Fr::char().as_ref(), &mut char_limbs); + for _ in 0..1000 { // Exponentiating by the modulus should have no effect in a prime field. let a = Fr::random(&mut rng); - assert_eq!(a, a.pow_vartime(Fr::char())); + assert_eq!(a, a.pow_vartime(char_limbs)); } } diff --git a/pairing/src/bls12_381/mod.rs b/pairing/src/bls12_381/mod.rs index 0f18053..afe9c82 100644 --- a/pairing/src/bls12_381/mod.rs +++ b/pairing/src/bls12_381/mod.rs @@ -23,7 +23,7 @@ pub use self::fr::{Fr, FrRepr}; use super::{Engine, PairingCurveAffine}; -use ff::{BitIterator, Field, PowVartime, ScalarEngine}; +use ff::{BitIterator, Field, ScalarEngine}; use group::CurveAffine; use std::ops::{AddAssign, MulAssign, Neg, SubAssign}; use subtle::CtOption; diff --git a/pairing/src/tests/engine.rs b/pairing/src/tests/engine.rs index c65816d..d4efb6d 100644 --- a/pairing/src/tests/engine.rs +++ b/pairing/src/tests/engine.rs @@ -1,10 +1,10 @@ -use ff::PowVartime; +use ff::{Endianness, Field, PrimeField}; use group::{CurveAffine, CurveProjective}; use rand_core::SeedableRng; use rand_xorshift::XorShiftRng; use std::ops::MulAssign; -use crate::{Engine, Field, PairingCurveAffine, PrimeField}; +use crate::{Engine, PairingCurveAffine}; pub fn engine_tests() { let mut rng = XorShiftRng::from_seed([ @@ -130,8 +130,14 @@ fn random_bilinearity_tests() { let mut cd = c; cd.mul_assign(&d); + let mut cd = cd.into_repr(); + ::ReprEndianness::toggle_little_endian(&mut cd); - let abcd = E::pairing(a, b).pow_vartime(cd.into_repr()); + use byteorder::ByteOrder; + let mut cd_limbs = [0; 4]; + byteorder::LittleEndian::read_u64_into(cd.as_ref(), &mut cd_limbs); + + let abcd = E::pairing(a, b).pow_vartime(cd_limbs); assert_eq!(acbd, adbc); assert_eq!(acbd, abcd); diff --git a/zcash_primitives/src/jubjub/fs.rs b/zcash_primitives/src/jubjub/fs.rs index 9f7c1b8..816c896 100644 --- a/zcash_primitives/src/jubjub/fs.rs +++ b/zcash_primitives/src/jubjub/fs.rs @@ -1,5 +1,5 @@ use byteorder::{ByteOrder, LittleEndian}; -use ff::{adc, mac_with_carry, sbb, BitIterator, Field, PowVartime, PrimeField}; +use ff::{adc, mac_with_carry, sbb, BitIterator, Field, PrimeField}; use rand_core::RngCore; use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; @@ -1051,11 +1051,15 @@ fn test_fs_pow() { assert_eq!(c, target); } + use byteorder::ByteOrder; + let mut char_limbs = [0; 4]; + byteorder::LittleEndian::read_u64_into(Fs::char().as_ref(), &mut char_limbs); + for _ in 0..1000 { // Exponentiating by the modulus should have no effect in a prime field. let a = Fs::random(&mut rng); - assert_eq!(a, a.pow_vartime(Fs::char())); + assert_eq!(a, a.pow_vartime(char_limbs)); } }