Merge pull request #192 from str4d/ff-pow_vartime-and-no_std

ff::Field::pow_vartime and no_std support
This commit is contained in:
ebfull
2019-12-19 08:56:02 -07:00
committed by GitHub
16 changed files with 136 additions and 124 deletions

View File

@@ -106,7 +106,7 @@ impl<E: ScalarEngine, G: Group<E>> EvaluationDomain<E, G> {
worker.scope(self.coeffs.len(), |scope, chunk| { worker.scope(self.coeffs.len(), |scope, chunk| {
for (i, v) in self.coeffs.chunks_mut(chunk).enumerate() { for (i, v) in self.coeffs.chunks_mut(chunk).enumerate() {
scope.spawn(move |_scope| { scope.spawn(move |_scope| {
let mut u = g.pow(&[(i * chunk) as u64]); let mut u = g.pow_vartime(&[(i * chunk) as u64]);
for v in v.iter_mut() { for v in v.iter_mut() {
v.group_mul_assign(&u); v.group_mul_assign(&u);
u.mul_assign(&g); u.mul_assign(&g);
@@ -131,7 +131,7 @@ impl<E: ScalarEngine, G: Group<E>> EvaluationDomain<E, G> {
/// This evaluates t(tau) for this domain, which is /// This evaluates t(tau) for this domain, which is
/// tau^m - 1 for these radix-2 domains. /// tau^m - 1 for these radix-2 domains.
pub fn z(&self, tau: &E::Fr) -> E::Fr { pub fn z(&self, tau: &E::Fr) -> E::Fr {
let mut tmp = tau.pow(&[self.coeffs.len() as u64]); let mut tmp = tau.pow_vartime(&[self.coeffs.len() as u64]);
tmp.sub_assign(&E::Fr::one()); tmp.sub_assign(&E::Fr::one());
tmp tmp
@@ -294,7 +294,7 @@ fn serial_fft<E: ScalarEngine, T: Group<E>>(a: &mut [T], omega: &E::Fr, log_n: u
let mut m = 1; let mut m = 1;
for _ in 0..log_n { for _ in 0..log_n {
let w_m = omega.pow(&[u64::from(n / (2 * m))]); let w_m = omega.pow_vartime(&[u64::from(n / (2 * m))]);
let mut k = 0; let mut k = 0;
while k < n { while k < n {
@@ -328,7 +328,7 @@ fn parallel_fft<E: ScalarEngine, T: Group<E>>(
let num_cpus = 1 << log_cpus; let num_cpus = 1 << log_cpus;
let log_new_n = log_n - log_cpus; let log_new_n = log_n - log_cpus;
let mut tmp = vec![vec![T::group_zero(); 1 << log_new_n]; num_cpus]; let mut tmp = vec![vec![T::group_zero(); 1 << log_new_n]; num_cpus];
let new_omega = omega.pow(&[num_cpus as u64]); let new_omega = omega.pow_vartime(&[num_cpus as u64]);
worker.scope(0, |scope, _| { worker.scope(0, |scope, _| {
let a = &*a; let a = &*a;
@@ -336,8 +336,8 @@ fn parallel_fft<E: ScalarEngine, T: Group<E>>(
for (j, tmp) in tmp.iter_mut().enumerate() { for (j, tmp) in tmp.iter_mut().enumerate() {
scope.spawn(move |_scope| { scope.spawn(move |_scope| {
// Shuffle into a sub-FFT // Shuffle into a sub-FFT
let omega_j = omega.pow(&[j as u64]); let omega_j = omega.pow_vartime(&[j as u64]);
let omega_step = omega.pow(&[(j as u64) << log_new_n]); let omega_step = omega.pow_vartime(&[(j as u64) << log_new_n]);
let mut elt = E::Fr::one(); let mut elt = E::Fr::one();
for (i, tmp) in tmp.iter_mut().enumerate() { for (i, tmp) in tmp.iter_mut().enumerate() {

View File

@@ -50,7 +50,9 @@ impl<E: ScalarEngine, CS: ConstraintSystem<E>> MultiEq<E, CS> {
assert!((E::Fr::CAPACITY as usize) > (self.bits_used + num_bits)); assert!((E::Fr::CAPACITY as usize) > (self.bits_used + num_bits));
let coeff = E::Fr::from_str("2").unwrap().pow(&[self.bits_used as u64]); let coeff = E::Fr::from_str("2")
.unwrap()
.pow_vartime(&[self.bits_used as u64]);
self.lhs = self.lhs.clone() + (coeff, lhs); self.lhs = self.lhs.clone() + (coeff, lhs);
self.rhs = self.rhs.clone() + (coeff, rhs); self.rhs = self.rhs.clone() + (coeff, rhs);
self.bits_used += num_bits; self.bits_used += num_bits;

View File

@@ -155,7 +155,7 @@ impl<E: ScalarEngine> TestConstraintSystem<E> {
let negone = E::Fr::one().neg(); let negone = E::Fr::one().neg();
let powers_of_two = (0..E::Fr::NUM_BITS) let powers_of_two = (0..E::Fr::NUM_BITS)
.map(|i| E::Fr::from_str("2").unwrap().pow(&[u64::from(i)])) .map(|i| E::Fr::from_str("2").unwrap().pow_vartime(&[u64::from(i)]))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let pp = |s: &mut String, lc: &LinearCombination<E>| { let pp = |s: &mut String, lc: &LinearCombination<E>| {

View File

@@ -242,7 +242,7 @@ where
worker.scope(powers_of_tau.len(), |scope, chunk| { worker.scope(powers_of_tau.len(), |scope, chunk| {
for (i, powers_of_tau) in powers_of_tau.chunks_mut(chunk).enumerate() { for (i, powers_of_tau) in powers_of_tau.chunks_mut(chunk).enumerate() {
scope.spawn(move |_scope| { scope.spawn(move |_scope| {
let mut current_tau_power = tau.pow(&[(i * chunk) as u64]); let mut current_tau_power = tau.pow_vartime(&[(i * chunk) as u64]);
for p in powers_of_tau { for p in powers_of_tau {
p.0 = current_tau_power; p.0 = current_tau_power;

View File

@@ -172,7 +172,10 @@ impl Field for Fr {
if <Fr as Field>::is_zero(self) { if <Fr as Field>::is_zero(self) {
CtOption::new(<Fr as Field>::zero(), Choice::from(0)) CtOption::new(<Fr as Field>::zero(), Choice::from(0))
} else { } else {
CtOption::new(self.pow(&[(MODULUS_R.0 as u64) - 2]), Choice::from(1)) CtOption::new(
self.pow_vartime(&[(MODULUS_R.0 as u64) - 2]),
Choice::from(1),
)
} }
} }
@@ -187,9 +190,9 @@ impl SqrtField for Fr {
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
let mut c = Fr::root_of_unity(); let mut c = Fr::root_of_unity();
// r = self^((t + 1) // 2) // r = self^((t + 1) // 2)
let mut r = self.pow([32]); let mut r = self.pow_vartime([32]);
// t = self^t // t = self^t
let mut t = self.pow([63]); let mut t = self.pow_vartime([63]);
let mut m = Fr::S; let mut m = Fr::S;
while t != <Fr as Field>::one() { while t != <Fr as Field>::one() {
@@ -311,7 +314,7 @@ impl PrimeField for Fr {
fn from_repr(repr: FrRepr) -> Result<Self, PrimeFieldDecodingError> { fn from_repr(repr: FrRepr) -> Result<Self, PrimeFieldDecodingError> {
if repr.0[0] >= (MODULUS_R.0 as u64) { if repr.0[0] >= (MODULUS_R.0 as u64) {
Err(PrimeFieldDecodingError::NotInField(format!("{}", repr))) Err(PrimeFieldDecodingError::NotInField)
} else { } else {
Ok(Fr(Wrapping(repr.0[0] as u32))) Ok(Fr(Wrapping(repr.0[0] as u32)))
} }

View File

@@ -127,22 +127,22 @@ fn test_xordemo() {
let mut root_of_unity = Fr::root_of_unity(); let mut root_of_unity = Fr::root_of_unity();
// We expect this to be a 2^10 root of unity // We expect this to be a 2^10 root of unity
assert_eq!(Fr::one(), root_of_unity.pow(&[1 << 10])); assert_eq!(Fr::one(), root_of_unity.pow_vartime(&[1 << 10]));
// Let's turn it into a 2^3 root of unity. // Let's turn it into a 2^3 root of unity.
root_of_unity = root_of_unity.pow(&[1 << 7]); root_of_unity = root_of_unity.pow_vartime(&[1 << 7]);
assert_eq!(Fr::one(), root_of_unity.pow(&[1 << 3])); assert_eq!(Fr::one(), root_of_unity.pow_vartime(&[1 << 3]));
assert_eq!(Fr::from_str("20201").unwrap(), root_of_unity); assert_eq!(Fr::from_str("20201").unwrap(), root_of_unity);
// Let's compute all the points in our evaluation domain. // Let's compute all the points in our evaluation domain.
let mut points = Vec::with_capacity(8); let mut points = Vec::with_capacity(8);
for i in 0..8 { for i in 0..8 {
points.push(root_of_unity.pow(&[i])); points.push(root_of_unity.pow_vartime(&[i]));
} }
// Let's compute t(tau) = (tau - p_0)(tau - p_1)... // Let's compute t(tau) = (tau - p_0)(tau - p_1)...
// = tau^8 - 1 // = tau^8 - 1
let mut t_at_tau = tau.pow(&[8]); let mut t_at_tau = tau.pow_vartime(&[8]);
t_at_tau.sub_assign(&Fr::one()); t_at_tau.sub_assign(&Fr::one());
{ {
let mut tmp = Fr::one(); let mut tmp = Fr::one();

View File

@@ -11,14 +11,15 @@ repository = "https://github.com/ebfull/ff"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
byteorder = "1" byteorder = { version = "1", default-features = false }
ff_derive = { version = "0.4.0", path = "ff_derive", optional = true } ff_derive = { version = "0.4.0", path = "ff_derive", optional = true }
rand_core = "0.5" rand_core = { version = "0.5", default-features = false }
subtle = "2.2.1" subtle = { version = "2.2.1", default-features = false, features = ["i128"] }
[features] [features]
default = [] default = ["std"]
derive = ["ff_derive"] derive = ["ff_derive"]
std = []
[badges] [badges]
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }

View File

@@ -113,9 +113,9 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS
#[derive(Copy, Clone, PartialEq, Eq, Default)] #[derive(Copy, Clone, PartialEq, Eq, Default)]
pub struct #repr(pub [u64; #limbs]); pub struct #repr(pub [u64; #limbs]);
impl ::std::fmt::Debug for #repr impl ::core::fmt::Debug for #repr
{ {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "0x")?; write!(f, "0x")?;
for i in self.0.iter().rev() { for i in self.0.iter().rev() {
write!(f, "{:016x}", *i)?; write!(f, "{:016x}", *i)?;
@@ -125,8 +125,8 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS
} }
} }
impl ::std::fmt::Display for #repr { impl ::core::fmt::Display for #repr {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "0x")?; write!(f, "0x")?;
for i in self.0.iter().rev() { for i in self.0.iter().rev() {
write!(f, "{:016x}", *i)?; write!(f, "{:016x}", *i)?;
@@ -153,7 +153,7 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS
impl From<u64> for #repr { impl From<u64> for #repr {
#[inline(always)] #[inline(always)]
fn from(val: u64) -> #repr { fn from(val: u64) -> #repr {
use std::default::Default; use core::default::Default;
let mut repr = Self::default(); let mut repr = Self::default();
repr.0[0] = val; repr.0[0] = val;
@@ -163,22 +163,22 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS
impl Ord for #repr { impl Ord for #repr {
#[inline(always)] #[inline(always)]
fn cmp(&self, other: &#repr) -> ::std::cmp::Ordering { fn cmp(&self, other: &#repr) -> ::core::cmp::Ordering {
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) { for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
if a < b { if a < b {
return ::std::cmp::Ordering::Less return ::core::cmp::Ordering::Less
} else if a > b { } else if a > b {
return ::std::cmp::Ordering::Greater return ::core::cmp::Ordering::Greater
} }
} }
::std::cmp::Ordering::Equal ::core::cmp::Ordering::Equal
} }
} }
impl PartialOrd for #repr { impl PartialOrd for #repr {
#[inline(always)] #[inline(always)]
fn partial_cmp(&self, other: &#repr) -> Option<::std::cmp::Ordering> { fn partial_cmp(&self, other: &#repr) -> Option<::core::cmp::Ordering> {
Some(self.cmp(other)) Some(self.cmp(other))
} }
} }
@@ -209,7 +209,7 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS
while n >= 64 { while n >= 64 {
let mut t = 0; let mut t = 0;
for i in self.0.iter_mut().rev() { for i in self.0.iter_mut().rev() {
::std::mem::swap(&mut t, i); ::core::mem::swap(&mut t, i);
} }
n -= 64; n -= 64;
} }
@@ -257,7 +257,7 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS
while n >= 64 { while n >= 64 {
let mut t = 0; let mut t = 0;
for i in &mut self.0 { for i in &mut self.0 {
::std::mem::swap(&mut t, i); ::core::mem::swap(&mut t, i);
} }
n -= 64; n -= 64;
} }
@@ -427,7 +427,7 @@ fn prime_field_constants_and_sqrt(
// Because r = 3 (mod 4) // Because r = 3 (mod 4)
// sqrt can be done with only one exponentiation, // sqrt can be done with only one exponentiation,
// via the computation of self^((r + 1) // 4) (mod r) // via the computation of self^((r + 1) // 4) (mod r)
let sqrt = self.pow(#mod_plus_1_over_4); let sqrt = self.pow_vartime(#mod_plus_1_over_4);
::subtle::CtOption::new( ::subtle::CtOption::new(
sqrt, sqrt,
@@ -447,7 +447,7 @@ fn prime_field_constants_and_sqrt(
use ::subtle::{ConditionallySelectable, ConstantTimeEq}; use ::subtle::{ConditionallySelectable, ConstantTimeEq};
// w = self^((t - 1) // 2) // w = self^((t - 1) // 2)
let w = self.pow(#t_minus_1_over_2); let w = self.pow_vartime(#t_minus_1_over_2);
let mut v = S; let mut v = S;
let mut x = *self * &w; let mut x = *self * &w;
@@ -767,15 +767,15 @@ fn prime_field_impl(
let top_limb_index = limbs - 1; let top_limb_index = limbs - 1;
quote! { quote! {
impl ::std::marker::Copy for #name { } impl ::core::marker::Copy for #name { }
impl ::std::clone::Clone for #name { impl ::core::clone::Clone for #name {
fn clone(&self) -> #name { fn clone(&self) -> #name {
*self *self
} }
} }
impl ::std::default::Default for #name { impl ::core::default::Default for #name {
fn default() -> #name { fn default() -> #name {
#name::zero() #name::zero()
} }
@@ -787,17 +787,17 @@ fn prime_field_impl(
} }
} }
impl ::std::cmp::PartialEq for #name { impl ::core::cmp::PartialEq for #name {
fn eq(&self, other: &#name) -> bool { fn eq(&self, other: &#name) -> bool {
self.0 == other.0 self.0 == other.0
} }
} }
impl ::std::cmp::Eq for #name { } impl ::core::cmp::Eq for #name { }
impl ::std::fmt::Debug for #name impl ::core::fmt::Debug for #name
{ {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{}({:?})", stringify!(#name), self.into_repr()) write!(f, "{}({:?})", stringify!(#name), self.into_repr())
} }
} }
@@ -805,20 +805,20 @@ fn prime_field_impl(
/// Elements are ordered lexicographically. /// Elements are ordered lexicographically.
impl Ord for #name { impl Ord for #name {
#[inline(always)] #[inline(always)]
fn cmp(&self, other: &#name) -> ::std::cmp::Ordering { fn cmp(&self, other: &#name) -> ::core::cmp::Ordering {
self.into_repr().cmp(&other.into_repr()) self.into_repr().cmp(&other.into_repr())
} }
} }
impl PartialOrd for #name { impl PartialOrd for #name {
#[inline(always)] #[inline(always)]
fn partial_cmp(&self, other: &#name) -> Option<::std::cmp::Ordering> { fn partial_cmp(&self, other: &#name) -> Option<::core::cmp::Ordering> {
Some(self.cmp(other)) Some(self.cmp(other))
} }
} }
impl ::std::fmt::Display for #name { impl ::core::fmt::Display for #name {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{}({})", stringify!(#name), self.into_repr()) write!(f, "{}({})", stringify!(#name), self.into_repr())
} }
} }
@@ -839,7 +839,7 @@ fn prime_field_impl(
} }
} }
impl ::std::ops::Neg for #name { impl ::core::ops::Neg for #name {
type Output = #name; type Output = #name;
#[inline] #[inline]
@@ -854,7 +854,7 @@ fn prime_field_impl(
} }
} }
impl<'r> ::std::ops::Add<&'r #name> for #name { impl<'r> ::core::ops::Add<&'r #name> for #name {
type Output = #name; type Output = #name;
#[inline] #[inline]
@@ -865,7 +865,7 @@ fn prime_field_impl(
} }
} }
impl ::std::ops::Add for #name { impl ::core::ops::Add for #name {
type Output = #name; type Output = #name;
#[inline] #[inline]
@@ -874,7 +874,7 @@ fn prime_field_impl(
} }
} }
impl<'r> ::std::ops::AddAssign<&'r #name> for #name { impl<'r> ::core::ops::AddAssign<&'r #name> for #name {
#[inline] #[inline]
fn add_assign(&mut self, other: &#name) { fn add_assign(&mut self, other: &#name) {
// This cannot exceed the backing capacity. // This cannot exceed the backing capacity.
@@ -885,14 +885,14 @@ fn prime_field_impl(
} }
} }
impl ::std::ops::AddAssign for #name { impl ::core::ops::AddAssign for #name {
#[inline] #[inline]
fn add_assign(&mut self, other: #name) { fn add_assign(&mut self, other: #name) {
self.add_assign(&other); self.add_assign(&other);
} }
} }
impl<'r> ::std::ops::Sub<&'r #name> for #name { impl<'r> ::core::ops::Sub<&'r #name> for #name {
type Output = #name; type Output = #name;
#[inline] #[inline]
@@ -903,7 +903,7 @@ fn prime_field_impl(
} }
} }
impl ::std::ops::Sub for #name { impl ::core::ops::Sub for #name {
type Output = #name; type Output = #name;
#[inline] #[inline]
@@ -912,7 +912,7 @@ fn prime_field_impl(
} }
} }
impl<'r> ::std::ops::SubAssign<&'r #name> for #name { impl<'r> ::core::ops::SubAssign<&'r #name> for #name {
#[inline] #[inline]
fn sub_assign(&mut self, other: &#name) { fn sub_assign(&mut self, other: &#name) {
// If `other` is larger than `self`, we'll need to add the modulus to self first. // If `other` is larger than `self`, we'll need to add the modulus to self first.
@@ -924,14 +924,14 @@ fn prime_field_impl(
} }
} }
impl ::std::ops::SubAssign for #name { impl ::core::ops::SubAssign for #name {
#[inline] #[inline]
fn sub_assign(&mut self, other: #name) { fn sub_assign(&mut self, other: #name) {
self.sub_assign(&other); self.sub_assign(&other);
} }
} }
impl<'r> ::std::ops::Mul<&'r #name> for #name { impl<'r> ::core::ops::Mul<&'r #name> for #name {
type Output = #name; type Output = #name;
#[inline] #[inline]
@@ -942,7 +942,7 @@ fn prime_field_impl(
} }
} }
impl ::std::ops::Mul for #name { impl ::core::ops::Mul for #name {
type Output = #name; type Output = #name;
#[inline] #[inline]
@@ -951,7 +951,7 @@ fn prime_field_impl(
} }
} }
impl<'r> ::std::ops::MulAssign<&'r #name> for #name { impl<'r> ::core::ops::MulAssign<&'r #name> for #name {
#[inline] #[inline]
fn mul_assign(&mut self, other: &#name) fn mul_assign(&mut self, other: &#name)
{ {
@@ -959,7 +959,7 @@ fn prime_field_impl(
} }
} }
impl ::std::ops::MulAssign for #name { impl ::core::ops::MulAssign for #name {
#[inline] #[inline]
fn mul_assign(&mut self, other: #name) fn mul_assign(&mut self, other: #name)
{ {
@@ -977,7 +977,7 @@ fn prime_field_impl(
Ok(r) Ok(r)
} else { } else {
Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0))) Err(PrimeFieldDecodingError::NotInField)
} }
} }

View File

@@ -1,17 +1,22 @@
//! This crate provides traits for working with finite fields. //! This crate provides traits for working with finite fields.
// Catch documentation errors caused by code changes. // Catch documentation errors caused by code changes.
#![no_std]
#![deny(intra_doc_link_resolution_failure)] #![deny(intra_doc_link_resolution_failure)]
#![allow(unused_imports)] #![allow(unused_imports)]
#[cfg(feature = "std")]
#[macro_use]
extern crate std;
#[cfg(feature = "derive")] #[cfg(feature = "derive")]
pub use ff_derive::*; pub use ff_derive::*;
use core::fmt;
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use rand_core::RngCore; use rand_core::RngCore;
use std::error::Error; #[cfg(feature = "std")]
use std::fmt;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use subtle::{ConditionallySelectable, CtOption}; use subtle::{ConditionallySelectable, CtOption};
/// This trait represents an element of a field. /// This trait represents an element of a field.
@@ -69,22 +74,20 @@ pub trait Field:
/// the Frobenius automorphism. /// the Frobenius automorphism.
fn frobenius_map(&mut self, power: usize); fn frobenius_map(&mut self, power: usize);
/// Exponentiates this element by a number represented with `u64` limbs, /// Exponentiates `self` by `exp`, where `exp` is a little-endian order
/// least significant digit first. /// integer exponent.
fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self { ///
/// **This operation is variable time with respect to the exponent.** If the
/// exponent is fixed, this operation is effectively constant time.
fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
let mut res = Self::one(); let mut res = Self::one();
for e in exp.as_ref().iter().rev() {
let mut found_one = false; for i in (0..64).rev() {
for i in BitIterator::new(exp) {
if found_one {
res = res.square(); res = res.square();
} else {
found_one = i;
}
if i { if ((*e >> i) & 1) == 1 {
res.mul_assign(self); res.mul_assign(self);
}
} }
} }
@@ -152,6 +155,7 @@ pub trait PrimeFieldRepr:
fn shl(&mut self, amt: u32); fn shl(&mut self, amt: u32);
/// Writes this `PrimeFieldRepr` as a big endian integer. /// Writes this `PrimeFieldRepr` as a big endian integer.
#[cfg(feature = "std")]
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> { fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{BigEndian, WriteBytesExt}; use byteorder::{BigEndian, WriteBytesExt};
@@ -163,6 +167,7 @@ pub trait PrimeFieldRepr:
} }
/// Reads a big endian integer into this representation. /// Reads a big endian integer into this representation.
#[cfg(feature = "std")]
fn read_be<R: Read>(&mut self, mut reader: R) -> io::Result<()> { fn read_be<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{BigEndian, ReadBytesExt}; use byteorder::{BigEndian, ReadBytesExt};
@@ -174,6 +179,7 @@ pub trait PrimeFieldRepr:
} }
/// Writes this `PrimeFieldRepr` as a little endian integer. /// Writes this `PrimeFieldRepr` as a little endian integer.
#[cfg(feature = "std")]
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> { fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{LittleEndian, WriteBytesExt}; use byteorder::{LittleEndian, WriteBytesExt};
@@ -185,6 +191,7 @@ pub trait PrimeFieldRepr:
} }
/// Reads a little endian integer into this representation. /// Reads a little endian integer into this representation.
#[cfg(feature = "std")]
fn read_le<R: Read>(&mut self, mut reader: R) -> io::Result<()> { fn read_le<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{LittleEndian, ReadBytesExt}; use byteorder::{LittleEndian, ReadBytesExt};
@@ -201,13 +208,14 @@ pub trait PrimeFieldRepr:
#[derive(Debug)] #[derive(Debug)]
pub enum PrimeFieldDecodingError { pub enum PrimeFieldDecodingError {
/// The encoded value is not in the field /// The encoded value is not in the field
NotInField(String), NotInField,
} }
impl Error for PrimeFieldDecodingError { #[cfg(feature = "std")]
impl std::error::Error for PrimeFieldDecodingError {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
PrimeFieldDecodingError::NotInField(..) => "not an element of the field", PrimeFieldDecodingError::NotInField => "not an element of the field",
} }
} }
} }
@@ -215,9 +223,7 @@ impl Error for PrimeFieldDecodingError {
impl fmt::Display for PrimeFieldDecodingError { impl fmt::Display for PrimeFieldDecodingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match *self { match *self {
PrimeFieldDecodingError::NotInField(ref repr) => { PrimeFieldDecodingError::NotInField => write!(f, "not an element of the field"),
write!(f, "{} is not an element of the field", repr)
}
} }
} }
} }

View File

@@ -464,7 +464,7 @@ fn test_frob_coeffs() {
assert_eq!(FROBENIUS_COEFF_FQ2_C1[0], Fq::one()); assert_eq!(FROBENIUS_COEFF_FQ2_C1[0], Fq::one());
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ2_C1[1], FROBENIUS_COEFF_FQ2_C1[1],
nqr.pow([ nqr.pow_vartime([
0xdcff7fffffffd555, 0xdcff7fffffffd555,
0xf55ffff58a9ffff, 0xf55ffff58a9ffff,
0xb39869507b587b12, 0xb39869507b587b12,
@@ -482,7 +482,7 @@ fn test_frob_coeffs() {
assert_eq!(FROBENIUS_COEFF_FQ6_C1[0], Fq2::one()); assert_eq!(FROBENIUS_COEFF_FQ6_C1[0], Fq2::one());
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C1[1], FROBENIUS_COEFF_FQ6_C1[1],
nqr.pow([ nqr.pow_vartime([
0x9354ffffffffe38e, 0x9354ffffffffe38e,
0xa395554e5c6aaaa, 0xa395554e5c6aaaa,
0xcd104635a790520c, 0xcd104635a790520c,
@@ -493,7 +493,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C1[2], FROBENIUS_COEFF_FQ6_C1[2],
nqr.pow([ nqr.pow_vartime([
0xb78e0000097b2f68, 0xb78e0000097b2f68,
0xd44f23b47cbd64e3, 0xd44f23b47cbd64e3,
0x5cb9668120b069a9, 0x5cb9668120b069a9,
@@ -510,7 +510,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C1[3], FROBENIUS_COEFF_FQ6_C1[3],
nqr.pow([ nqr.pow_vartime([
0xdbc6fcd6f35b9e06, 0xdbc6fcd6f35b9e06,
0x997dead10becd6aa, 0x997dead10becd6aa,
0x9dbbd24c17206460, 0x9dbbd24c17206460,
@@ -533,7 +533,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C1[4], FROBENIUS_COEFF_FQ6_C1[4],
nqr.pow([ nqr.pow_vartime([
0x4649add3c71c6d90, 0x4649add3c71c6d90,
0x43caa6528972a865, 0x43caa6528972a865,
0xcda8445bbaaa0fbb, 0xcda8445bbaaa0fbb,
@@ -562,7 +562,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C1[5], FROBENIUS_COEFF_FQ6_C1[5],
nqr.pow([ nqr.pow_vartime([
0xf896f792732eb2be, 0xf896f792732eb2be,
0x49c86a6d1dc593a1, 0x49c86a6d1dc593a1,
0xe5b31e94581f91c3, 0xe5b31e94581f91c3,
@@ -599,7 +599,7 @@ fn test_frob_coeffs() {
assert_eq!(FROBENIUS_COEFF_FQ6_C2[0], Fq2::one()); assert_eq!(FROBENIUS_COEFF_FQ6_C2[0], Fq2::one());
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C2[1], FROBENIUS_COEFF_FQ6_C2[1],
nqr.pow([ nqr.pow_vartime([
0x26a9ffffffffc71c, 0x26a9ffffffffc71c,
0x1472aaa9cb8d5555, 0x1472aaa9cb8d5555,
0x9a208c6b4f20a418, 0x9a208c6b4f20a418,
@@ -610,7 +610,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C2[2], FROBENIUS_COEFF_FQ6_C2[2],
nqr.pow([ nqr.pow_vartime([
0x6f1c000012f65ed0, 0x6f1c000012f65ed0,
0xa89e4768f97ac9c7, 0xa89e4768f97ac9c7,
0xb972cd024160d353, 0xb972cd024160d353,
@@ -627,7 +627,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C2[3], FROBENIUS_COEFF_FQ6_C2[3],
nqr.pow([ nqr.pow_vartime([
0xb78df9ade6b73c0c, 0xb78df9ade6b73c0c,
0x32fbd5a217d9ad55, 0x32fbd5a217d9ad55,
0x3b77a4982e40c8c1, 0x3b77a4982e40c8c1,
@@ -650,7 +650,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C2[4], FROBENIUS_COEFF_FQ6_C2[4],
nqr.pow([ nqr.pow_vartime([
0x8c935ba78e38db20, 0x8c935ba78e38db20,
0x87954ca512e550ca, 0x87954ca512e550ca,
0x9b5088b775541f76, 0x9b5088b775541f76,
@@ -679,7 +679,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ6_C2[5], FROBENIUS_COEFF_FQ6_C2[5],
nqr.pow([ nqr.pow_vartime([
0xf12def24e65d657c, 0xf12def24e65d657c,
0x9390d4da3b8b2743, 0x9390d4da3b8b2743,
0xcb663d28b03f2386, 0xcb663d28b03f2386,
@@ -716,7 +716,7 @@ fn test_frob_coeffs() {
assert_eq!(FROBENIUS_COEFF_FQ12_C1[0], Fq2::one()); assert_eq!(FROBENIUS_COEFF_FQ12_C1[0], Fq2::one());
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[1], FROBENIUS_COEFF_FQ12_C1[1],
nqr.pow([ nqr.pow_vartime([
0x49aa7ffffffff1c7, 0x49aa7ffffffff1c7,
0x51caaaa72e35555, 0x51caaaa72e35555,
0xe688231ad3c82906, 0xe688231ad3c82906,
@@ -727,7 +727,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[2], FROBENIUS_COEFF_FQ12_C1[2],
nqr.pow([ nqr.pow_vartime([
0xdbc7000004bd97b4, 0xdbc7000004bd97b4,
0xea2791da3e5eb271, 0xea2791da3e5eb271,
0x2e5cb340905834d4, 0x2e5cb340905834d4,
@@ -744,7 +744,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[3], FROBENIUS_COEFF_FQ12_C1[3],
nqr.pow(vec![ nqr.pow_vartime(vec![
0x6de37e6b79adcf03, 0x6de37e6b79adcf03,
0x4cbef56885f66b55, 0x4cbef56885f66b55,
0x4edde9260b903230, 0x4edde9260b903230,
@@ -767,7 +767,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[4], FROBENIUS_COEFF_FQ12_C1[4],
nqr.pow(vec![ nqr.pow_vartime(vec![
0xa324d6e9e38e36c8, 0xa324d6e9e38e36c8,
0xa1e5532944b95432, 0xa1e5532944b95432,
0x66d4222ddd5507dd, 0x66d4222ddd5507dd,
@@ -796,7 +796,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[5], FROBENIUS_COEFF_FQ12_C1[5],
nqr.pow(vec![ nqr.pow_vartime(vec![
0xfc4b7bc93997595f, 0xfc4b7bc93997595f,
0xa4e435368ee2c9d0, 0xa4e435368ee2c9d0,
0xf2d98f4a2c0fc8e1, 0xf2d98f4a2c0fc8e1,
@@ -831,7 +831,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[6], FROBENIUS_COEFF_FQ12_C1[6],
nqr.pow(vec![ nqr.pow_vartime(vec![
0x21219610a012ba3c, 0x21219610a012ba3c,
0xa5c19ad35375325, 0xa5c19ad35375325,
0x4e9df1e497674396, 0x4e9df1e497674396,
@@ -872,7 +872,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[7], FROBENIUS_COEFF_FQ12_C1[7],
nqr.pow(vec![ nqr.pow_vartime(vec![
0x742754a1f22fdb, 0x742754a1f22fdb,
0x2a1955c2dec3a702, 0x2a1955c2dec3a702,
0x9747b28c796d134e, 0x9747b28c796d134e,
@@ -919,7 +919,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[8], FROBENIUS_COEFF_FQ12_C1[8],
nqr.pow(vec![ nqr.pow_vartime(vec![
0x802f5720d0b25710, 0x802f5720d0b25710,
0x6714f0a258b85c7c, 0x6714f0a258b85c7c,
0x31394c90afdf16e, 0x31394c90afdf16e,
@@ -972,7 +972,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[9], FROBENIUS_COEFF_FQ12_C1[9],
nqr.pow(vec![ nqr.pow_vartime(vec![
0x4af4accf7de0b977, 0x4af4accf7de0b977,
0x742485e21805b4ee, 0x742485e21805b4ee,
0xee388fbc4ac36dec, 0xee388fbc4ac36dec,
@@ -1031,7 +1031,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[10], FROBENIUS_COEFF_FQ12_C1[10],
nqr.pow(vec![ nqr.pow_vartime(vec![
0xe5953a4f96cdda44, 0xe5953a4f96cdda44,
0x336b2d734cbc32bb, 0x336b2d734cbc32bb,
0x3f79bfe3cd7410e, 0x3f79bfe3cd7410e,
@@ -1096,7 +1096,7 @@ fn test_frob_coeffs() {
); );
assert_eq!( assert_eq!(
FROBENIUS_COEFF_FQ12_C1[11], FROBENIUS_COEFF_FQ12_C1[11],
nqr.pow(vec![ nqr.pow_vartime(vec![
0x107db680942de533, 0x107db680942de533,
0x6262b24d2052393b, 0x6262b24d2052393b,
0x6136df824159ebc, 0x6136df824159ebc,
@@ -2032,7 +2032,7 @@ fn test_fq_pow() {
// Exponentiate by various small numbers and ensure it consists with repeated // Exponentiate by various small numbers and ensure it consists with repeated
// multiplication. // multiplication.
let a = Fq::random(&mut rng); let a = Fq::random(&mut rng);
let target = a.pow(&[i]); let target = a.pow_vartime(&[i]);
let mut c = Fq::one(); let mut c = Fq::one();
for _ in 0..i { for _ in 0..i {
c.mul_assign(&a); c.mul_assign(&a);
@@ -2044,7 +2044,7 @@ fn test_fq_pow() {
// Exponentiating by the modulus should have no effect in a prime field. // Exponentiating by the modulus should have no effect in a prime field.
let a = Fq::random(&mut rng); let a = Fq::random(&mut rng);
assert_eq!(a, a.pow(Fq::char())); assert_eq!(a, a.pow_vartime(Fq::char()));
} }
} }
@@ -2195,7 +2195,7 @@ fn test_fq_root_of_unity() {
Fq::from_repr(FqRepr::from(2)).unwrap() Fq::from_repr(FqRepr::from(2)).unwrap()
); );
assert_eq!( assert_eq!(
Fq::multiplicative_generator().pow([ Fq::multiplicative_generator().pow_vartime([
0xdcff7fffffffd555, 0xdcff7fffffffd555,
0xf55ffff58a9ffff, 0xf55ffff58a9ffff,
0xb39869507b587b12, 0xb39869507b587b12,
@@ -2205,7 +2205,7 @@ fn test_fq_root_of_unity() {
]), ]),
Fq::root_of_unity() Fq::root_of_unity()
); );
assert_eq!(Fq::root_of_unity().pow([1 << Fq::S]), Fq::one()); assert_eq!(Fq::root_of_unity().pow_vartime([1 << Fq::S]), Fq::one());
assert!(bool::from(Fq::multiplicative_generator().sqrt().is_none())); assert!(bool::from(Fq::multiplicative_generator().sqrt().is_none()));
} }

View File

@@ -253,7 +253,7 @@ impl SqrtField for Fq2 {
CtOption::new(Self::zero(), Choice::from(1)) CtOption::new(Self::zero(), Choice::from(1))
} else { } else {
// a1 = self^((q - 3) / 4) // a1 = self^((q - 3) / 4)
let mut a1 = self.pow([ let mut a1 = self.pow_vartime([
0xee7fbfffffffeaaa, 0xee7fbfffffffeaaa,
0x7aaffffac54ffff, 0x7aaffffac54ffff,
0xd9cc34a83dac3d89, 0xd9cc34a83dac3d89,
@@ -285,7 +285,7 @@ impl SqrtField for Fq2 {
} else { } else {
alpha.add_assign(&Fq2::one()); alpha.add_assign(&Fq2::one());
// alpha = alpha^((q - 1) / 2) // alpha = alpha^((q - 1) / 2)
alpha = alpha.pow([ alpha = alpha.pow_vartime([
0xdcff7fffffffd555, 0xdcff7fffffffd555,
0xf55ffff58a9ffff, 0xf55ffff58a9ffff,
0xb39869507b587b12, 0xb39869507b587b12,

View File

@@ -767,7 +767,7 @@ fn test_fr_pow() {
// Exponentiate by various small numbers and ensure it consists with repeated // Exponentiate by various small numbers and ensure it consists with repeated
// multiplication. // multiplication.
let a = Fr::random(&mut rng); let a = Fr::random(&mut rng);
let target = a.pow(&[i]); let target = a.pow_vartime(&[i]);
let mut c = Fr::one(); let mut c = Fr::one();
for _ in 0..i { for _ in 0..i {
c.mul_assign(&a); c.mul_assign(&a);
@@ -779,7 +779,7 @@ fn test_fr_pow() {
// Exponentiating by the modulus should have no effect in a prime field. // Exponentiating by the modulus should have no effect in a prime field.
let a = Fr::random(&mut rng); let a = Fr::random(&mut rng);
assert_eq!(a, a.pow(Fr::char())); assert_eq!(a, a.pow_vartime(Fr::char()));
} }
} }
@@ -964,7 +964,7 @@ fn test_fr_root_of_unity() {
Fr::from_repr(FrRepr::from(7)).unwrap() Fr::from_repr(FrRepr::from(7)).unwrap()
); );
assert_eq!( assert_eq!(
Fr::multiplicative_generator().pow([ Fr::multiplicative_generator().pow_vartime([
0xfffe5bfeffffffff, 0xfffe5bfeffffffff,
0x9a1d80553bda402, 0x9a1d80553bda402,
0x299d7d483339d808, 0x299d7d483339d808,
@@ -972,7 +972,7 @@ fn test_fr_root_of_unity() {
]), ]),
Fr::root_of_unity() Fr::root_of_unity()
); );
assert_eq!(Fr::root_of_unity().pow([1 << Fr::S]), Fr::one()); assert_eq!(Fr::root_of_unity().pow_vartime([1 << Fr::S]), Fr::one());
assert!(bool::from(Fr::multiplicative_generator().sqrt().is_none())); assert!(bool::from(Fr::multiplicative_generator().sqrt().is_none()));
} }

View File

@@ -124,7 +124,7 @@ impl Engine for Bls12 {
r.mul_assign(&f2); r.mul_assign(&f2);
fn exp_by_x(f: &mut Fq12, x: u64) { fn exp_by_x(f: &mut Fq12, x: u64) {
*f = f.pow(&[x]); *f = f.pow_vartime(&[x]);
if BLS_X_IS_NEGATIVE { if BLS_X_IS_NEGATIVE {
f.conjugate(); f.conjugate();
} }

View File

@@ -130,7 +130,7 @@ fn random_bilinearity_tests<E: Engine>() {
let mut cd = c; let mut cd = c;
cd.mul_assign(&d); cd.mul_assign(&d);
let abcd = E::pairing(a, b).pow(cd.into_repr()); let abcd = E::pairing(a, b).pow_vartime(cd.into_repr());
assert_eq!(acbd, adbc); assert_eq!(acbd, adbc);
assert_eq!(acbd, abcd); assert_eq!(acbd, abcd);

View File

@@ -14,7 +14,7 @@ pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxp
let mut b = a; let mut b = a;
for _ in 0..i { for _ in 0..i {
a = a.pow(&characteristic); a = a.pow_vartime(&characteristic);
} }
b.frobenius_map(i); b.frobenius_map(i);

View File

@@ -454,7 +454,7 @@ impl PrimeField for Fs {
Ok(r) Ok(r)
} else { } else {
Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0))) Err(PrimeFieldDecodingError::NotInField)
} }
} }
@@ -744,7 +744,7 @@ impl SqrtField for Fs {
// https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2)
// a1 = self^((s - 3) // 4) // a1 = self^((s - 3) // 4)
let mut a1 = self.pow([ let mut a1 = self.pow_vartime([
0xb425c397b5bdcb2d, 0xb425c397b5bdcb2d,
0x299a0824f3320420, 0x299a0824f3320420,
0x4199cec0404d0ec0, 0x4199cec0404d0ec0,
@@ -1495,7 +1495,7 @@ fn test_fs_pow() {
// Exponentiate by various small numbers and ensure it consists with repeated // Exponentiate by various small numbers and ensure it consists with repeated
// multiplication. // multiplication.
let a = Fs::random(&mut rng); let a = Fs::random(&mut rng);
let target = a.pow(&[i]); let target = a.pow_vartime(&[i]);
let mut c = Fs::one(); let mut c = Fs::one();
for _ in 0..i { for _ in 0..i {
c.mul_assign(&a); c.mul_assign(&a);
@@ -1507,7 +1507,7 @@ fn test_fs_pow() {
// Exponentiating by the modulus should have no effect in a prime field. // Exponentiating by the modulus should have no effect in a prime field.
let a = Fs::random(&mut rng); let a = Fs::random(&mut rng);
assert_eq!(a, a.pow(Fs::char())); assert_eq!(a, a.pow_vartime(Fs::char()));
} }
} }
@@ -1688,7 +1688,7 @@ fn test_fs_root_of_unity() {
Fs::from_repr(FsRepr::from(6)).unwrap() Fs::from_repr(FsRepr::from(6)).unwrap()
); );
assert_eq!( assert_eq!(
Fs::multiplicative_generator().pow([ Fs::multiplicative_generator().pow_vartime([
0x684b872f6b7b965b, 0x684b872f6b7b965b,
0x53341049e6640841, 0x53341049e6640841,
0x83339d80809a1d80, 0x83339d80809a1d80,
@@ -1696,6 +1696,6 @@ fn test_fs_root_of_unity() {
]), ]),
Fs::root_of_unity() Fs::root_of_unity()
); );
assert_eq!(Fs::root_of_unity().pow([1 << Fs::S]), Fs::one()); assert_eq!(Fs::root_of_unity().pow_vartime([1 << Fs::S]), Fs::one());
assert!(bool::from(Fs::multiplicative_generator().sqrt().is_none())); assert!(bool::from(Fs::multiplicative_generator().sqrt().is_none()));
} }