ff: Move pow_vartime into a trait that is generic over the limb size

The trait is implemented by default for u8 and u64, allowing pow_vartime
to be used with both the byte encoding and limb representation of field
elements.
This commit is contained in:
Jack Grigg
2020-03-27 22:35:55 +13:00
parent 69c60530d4
commit b6457a905b
14 changed files with 89 additions and 55 deletions

View File

@@ -13,7 +13,7 @@ extern crate std;
pub use ff_derive::*;
use core::fmt;
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::ops::{Add, AddAssign, BitAnd, Mul, MulAssign, Neg, Shr, Sub, SubAssign};
use rand_core::RngCore;
#[cfg(feature = "std")]
use std::io::{self, Read, Write};
@@ -73,21 +73,36 @@ pub trait Field:
/// Exponentiates this element by a power of the base prime modulus via
/// the Frobenius automorphism.
fn frobenius_map(&mut self, power: usize);
}
pub trait PowVartime<L>: Field
where
L: Copy + PartialEq + PartialOrd + AddAssign,
L: BitAnd<Output = L>,
L: Shr<Output = L>,
L: Sub<Output = L>,
{
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<S: AsRef<[u64]>>(&self, exp: S) -> Self {
fn pow_vartime<S: AsRef<[L]>>(&self, exp: S) -> Self {
let mut res = Self::one();
for e in exp.as_ref().iter().rev() {
for i in (0..64).rev() {
let mut i = Self::ZERO;
while i < Self::LIMB_SIZE {
res = res.square();
if ((*e >> i) & 1) == 1 {
if ((*e >> (Self::LIMB_SIZE - Self::ONE - i)) & Self::ONE) == Self::ONE {
res.mul_assign(self);
}
i += Self::ONE;
}
}
@@ -95,6 +110,18 @@ pub trait Field:
}
}
impl<T: Field> PowVartime<u8> for T {
const ZERO: u8 = 0;
const ONE: u8 = 1;
const LIMB_SIZE: u8 = 8;
}
impl<T: Field> PowVartime<u64> for T {
const ZERO: u64 = 0;
const ONE: u64 = 1;
const LIMB_SIZE: u64 = 64;
}
/// This trait represents an element of a field that has a square root operation described for it.
pub trait SqrtField: Field {
/// Returns the square root of the field element, if it is