diff --git a/benches/bls12_381/fr.rs b/benches/bls12_381/fr.rs index 13b0d0e85..9cab67136 100644 --- a/benches/bls12_381/fr.rs +++ b/benches/bls12_381/fr.rs @@ -1,6 +1,6 @@ use rand::{Rand, SeedableRng, XorShiftRng}; -use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; +use ff::{Field, PrimeField, PrimeFieldRepr}; use pairing::bls12_381::*; #[bench] diff --git a/src/bls12_381/fq.rs b/src/bls12_381/fq.rs index e10929432..2b4b7a6db 100644 --- a/src/bls12_381/fq.rs +++ b/src/bls12_381/fq.rs @@ -1,69 +1,5 @@ use super::fq2::Fq2; -use std::cmp::Ordering; -use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; - -// q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 -const MODULUS: FqRepr = FqRepr([ - 0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a, -]); - -// The number of bits needed to represent the modulus. -const MODULUS_BITS: u32 = 381; - -// The number of bits that must be shaved from the beginning of -// the representation when randomly sampling. -const REPR_SHAVE_BITS: u32 = 3; - -// R = 2**384 % q -const R: FqRepr = FqRepr([ - 0x760900000002fffd, - 0xebf4000bc40c0002, - 0x5f48985753c758ba, - 0x77ce585370525745, - 0x5c071a97a256ec6d, - 0x15f65ec3fa80e493, -]); - -// R2 = R^2 % q -const R2: FqRepr = FqRepr([ - 0xf4df1f341c341746, - 0xa76e6a609d104f1, - 0x8de5476c4c95b6d5, - 0x67eb88a9939d83c0, - 0x9a793e85b519952d, - 0x11988fe592cae3aa, -]); - -// INV = -(q^{-1} mod 2^64) mod 2^64 -const INV: u64 = 0x89f3fffcfffcfffd; - -// GENERATOR = 2 (multiplicative generator of q-1 order, that is also quadratic nonresidue) -const GENERATOR: FqRepr = FqRepr([ - 0x321300000006554f, - 0xb93c0018d6c40005, - 0x57605e0db0ddbb51, - 0x8b256521ed1f9bcb, - 0x6cf28d7901622c03, - 0x11ebab9dbb81e28c, -]); - -// 2^s * t = MODULUS - 1 with t odd -const S: u32 = 1; - -// 2^s root of unity computed by GENERATOR^t -const ROOT_OF_UNITY: FqRepr = FqRepr([ - 0x43f5fffffffcaaae, - 0x32b7fff2ed47fffd, - 0x7e83a49a2e99d69, - 0xeca8f3318332bb7a, - 0xef148d1ea0f4c069, - 0x40ab3263eff0206, -]); +use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; // B coefficient of BLS12-381 curve, 4. pub const B_COEFF: Fq = Fq(FqRepr([ @@ -507,667 +443,11 @@ pub const NEGATIVE_ONE: Fq = Fq(FqRepr([ 0x40ab3263eff0206, ])); -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] -pub struct FqRepr(pub [u64; 6]); - -impl ::rand::Rand for FqRepr { - #[inline(always)] - fn rand(rng: &mut R) -> Self { - FqRepr(rng.gen()) - } -} - -impl ::std::fmt::Display for FqRepr { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - try!(write!(f, "0x")); - for i in self.0.iter().rev() { - try!(write!(f, "{:016x}", *i)); - } - - Ok(()) - } -} - -impl AsRef<[u64]> for FqRepr { - #[inline(always)] - fn as_ref(&self) -> &[u64] { - &self.0 - } -} - -impl AsMut<[u64]> for FqRepr { - #[inline(always)] - fn as_mut(&mut self) -> &mut [u64] { - &mut self.0 - } -} - -impl From for FqRepr { - #[inline(always)] - fn from(val: u64) -> FqRepr { - let mut repr = Self::default(); - repr.0[0] = val; - repr - } -} - -impl Ord for FqRepr { - #[inline(always)] - fn cmp(&self, other: &FqRepr) -> Ordering { - for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) { - if a < b { - return Ordering::Less; - } else if a > b { - return Ordering::Greater; - } - } - - Ordering::Equal - } -} - -impl PartialOrd for FqRepr { - #[inline(always)] - fn partial_cmp(&self, other: &FqRepr) -> Option { - Some(self.cmp(other)) - } -} - -impl PrimeFieldRepr for FqRepr { - #[inline(always)] - fn is_odd(&self) -> bool { - self.0[0] & 1 == 1 - } - - #[inline(always)] - fn is_even(&self) -> bool { - !self.is_odd() - } - - #[inline(always)] - fn is_zero(&self) -> bool { - self.0.iter().all(|&e| e == 0) - } - - #[inline(always)] - fn shr(&mut self, mut n: u32) { - if n >= 64 * 6 { - *self = Self::from(0); - return; - } - - while n >= 64 { - let mut t = 0; - for i in self.0.iter_mut().rev() { - ::std::mem::swap(&mut t, i); - } - n -= 64; - } - - if n > 0 { - let mut t = 0; - for i in self.0.iter_mut().rev() { - let t2 = *i << (64 - n); - *i >>= n; - *i |= t; - t = t2; - } - } - } - - #[inline(always)] - fn div2(&mut self) { - let mut t = 0; - for i in self.0.iter_mut().rev() { - let t2 = *i << 63; - *i >>= 1; - *i |= t; - t = t2; - } - } - - #[inline(always)] - fn mul2(&mut self) { - let mut last = 0; - for i in &mut self.0 { - let tmp = *i >> 63; - *i <<= 1; - *i |= last; - last = tmp; - } - } - - #[inline(always)] - fn shl(&mut self, mut n: u32) { - if n >= 64 * 6 { - *self = Self::from(0); - return; - } - - while n >= 64 { - let mut t = 0; - for i in &mut self.0 { - ::std::mem::swap(&mut t, i); - } - n -= 64; - } - - if n > 0 { - let mut t = 0; - for i in &mut self.0 { - let t2 = *i >> (64 - n); - *i <<= n; - *i |= t; - t = t2; - } - } - } - - #[inline(always)] - fn num_bits(&self) -> u32 { - let mut ret = (6 as u32) * 64; - for i in self.0.iter().rev() { - let leading = i.leading_zeros(); - ret -= leading; - if leading != 64 { - break; - } - } - - ret - } - - #[inline(always)] - fn add_nocarry(&mut self, other: &FqRepr) { - let mut carry = 0; - - for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::ff::adc(*a, *b, &mut carry); - } - } - - #[inline(always)] - fn sub_noborrow(&mut self, other: &FqRepr) { - let mut borrow = 0; - - for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::ff::sbb(*a, *b, &mut borrow); - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(PrimeField)] +#[PrimeFieldModulus = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"] +#[PrimeFieldGenerator = "2"] pub struct Fq(FqRepr); -/// `Fq` elements are ordered lexicographically. -impl Ord for Fq { - #[inline(always)] - fn cmp(&self, other: &Fq) -> Ordering { - self.into_repr().cmp(&other.into_repr()) - } -} - -impl PartialOrd for Fq { - #[inline(always)] - fn partial_cmp(&self, other: &Fq) -> Option { - Some(self.cmp(other)) - } -} - -impl ::std::fmt::Display for Fq { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "Fq({})", self.into_repr()) - } -} - -impl ::rand::Rand for Fq { - fn rand(rng: &mut R) -> Self { - loop { - let mut tmp = Fq(FqRepr::rand(rng)); - - // Mask away the unused bits at the beginning. - tmp.0.as_mut()[5] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; - - if tmp.is_valid() { - return tmp; - } - } - } -} - -impl From for FqRepr { - fn from(e: Fq) -> FqRepr { - e.into_repr() - } -} - -impl PrimeField for Fq { - type Repr = FqRepr; - - fn from_repr(r: FqRepr) -> Result { - let mut r = Fq(r); - if r.is_valid() { - r.mul_assign(&Fq(R2)); - - Ok(r) - } else { - Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0))) - } - } - - fn into_repr(&self) -> FqRepr { - let mut r = *self; - r.mont_reduce( - (self.0).0[0], - (self.0).0[1], - (self.0).0[2], - (self.0).0[3], - (self.0).0[4], - (self.0).0[5], - 0, - 0, - 0, - 0, - 0, - 0, - ); - r.0 - } - - fn char() -> FqRepr { - MODULUS - } - - const NUM_BITS: u32 = MODULUS_BITS; - - const CAPACITY: u32 = Self::NUM_BITS - 1; - - fn multiplicative_generator() -> Self { - Fq(GENERATOR) - } - - const S: u32 = S; - - fn root_of_unity() -> Self { - Fq(ROOT_OF_UNITY) - } -} - -impl Field for Fq { - #[inline] - fn zero() -> Self { - Fq(FqRepr::from(0)) - } - - #[inline] - fn one() -> Self { - Fq(R) - } - - #[inline] - fn is_zero(&self) -> bool { - self.0.is_zero() - } - - #[inline] - fn add_assign(&mut self, other: &Fq) { - // This cannot exceed the backing capacity. - self.0.add_nocarry(&other.0); - - // However, it may need to be reduced. - self.reduce(); - } - - #[inline] - fn double(&mut self) { - // This cannot exceed the backing capacity. - self.0.mul2(); - - // However, it may need to be reduced. - self.reduce(); - } - - #[inline] - fn sub_assign(&mut self, other: &Fq) { - // If `other` is larger than `self`, we'll need to add the modulus to self first. - if other.0 > self.0 { - self.0.add_nocarry(&MODULUS); - } - - self.0.sub_noborrow(&other.0); - } - - #[inline] - fn negate(&mut self) { - if !self.is_zero() { - let mut tmp = MODULUS; - tmp.sub_noborrow(&self.0); - self.0 = tmp; - } - } - - fn inverse(&self) -> Option { - if self.is_zero() { - None - } else { - // Guajardo Kumar Paar Pelzl - // Efficient Software-Implementation of Finite Fields with Applications to Cryptography - // Algorithm 16 (BEA for Inversion in Fp) - - let one = FqRepr::from(1); - - let mut u = self.0; - let mut v = MODULUS; - let mut b = Fq(R2); // Avoids unnecessary reduction step. - let mut c = Self::zero(); - - while u != one && v != one { - while u.is_even() { - u.div2(); - - if b.0.is_even() { - b.0.div2(); - } else { - b.0.add_nocarry(&MODULUS); - b.0.div2(); - } - } - - while v.is_even() { - v.div2(); - - if c.0.is_even() { - c.0.div2(); - } else { - c.0.add_nocarry(&MODULUS); - c.0.div2(); - } - } - - if v < u { - u.sub_noborrow(&v); - b.sub_assign(&c); - } else { - v.sub_noborrow(&u); - c.sub_assign(&b); - } - } - - if u == one { - Some(b) - } else { - Some(c) - } - } - } - - #[inline(always)] - fn frobenius_map(&mut self, _: usize) { - // This has no effect in a prime field. - } - - #[inline] - fn mul_assign(&mut self, other: &Fq) { - let mut carry = 0; - let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); - let r4 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[4], &mut carry); - let r5 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[5], &mut carry); - let r6 = carry; - let mut carry = 0; - let r1 = ::ff::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[1], (other.0).0[4], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[1], (other.0).0[5], &mut carry); - let r7 = carry; - let mut carry = 0; - let r2 = ::ff::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = ::ff::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[2], (other.0).0[4], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[2], (other.0).0[5], &mut carry); - let r8 = carry; - let mut carry = 0; - let r3 = ::ff::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[3], (other.0).0[4], &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[3], (other.0).0[5], &mut carry); - let r9 = carry; - let mut carry = 0; - let r4 = ::ff::mac_with_carry(r4, (self.0).0[4], (other.0).0[0], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[4], (other.0).0[1], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[4], (other.0).0[2], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[4], (other.0).0[3], &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[4], (other.0).0[4], &mut carry); - let r9 = ::ff::mac_with_carry(r9, (self.0).0[4], (other.0).0[5], &mut carry); - let r10 = carry; - let mut carry = 0; - let r5 = ::ff::mac_with_carry(r5, (self.0).0[5], (other.0).0[0], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[5], (other.0).0[1], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[5], (other.0).0[2], &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[5], (other.0).0[3], &mut carry); - let r9 = ::ff::mac_with_carry(r9, (self.0).0[5], (other.0).0[4], &mut carry); - let r10 = ::ff::mac_with_carry(r10, (self.0).0[5], (other.0).0[5], &mut carry); - let r11 = carry; - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11); - } - - #[inline] - fn square(&mut self) { - let mut carry = 0; - let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); - let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); - let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); - let r4 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[4], &mut carry); - let r5 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[5], &mut carry); - let r6 = carry; - let mut carry = 0; - let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[1], (self.0).0[4], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[1], (self.0).0[5], &mut carry); - let r7 = carry; - let mut carry = 0; - let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[2], (self.0).0[4], &mut carry); - let r7 = ::ff::mac_with_carry(r7, (self.0).0[2], (self.0).0[5], &mut carry); - let r8 = carry; - let mut carry = 0; - let r7 = ::ff::mac_with_carry(r7, (self.0).0[3], (self.0).0[4], &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[3], (self.0).0[5], &mut carry); - let r9 = carry; - let mut carry = 0; - let r9 = ::ff::mac_with_carry(r9, (self.0).0[4], (self.0).0[5], &mut carry); - let r10 = carry; - - let r11 = r10 >> 63; - let r10 = (r10 << 1) | (r9 >> 63); - let r9 = (r9 << 1) | (r8 >> 63); - let r8 = (r8 << 1) | (r7 >> 63); - let r7 = (r7 << 1) | (r6 >> 63); - let r6 = (r6 << 1) | (r5 >> 63); - let r5 = (r5 << 1) | (r4 >> 63); - let r4 = (r4 << 1) | (r3 >> 63); - let r3 = (r3 << 1) | (r2 >> 63); - let r2 = (r2 << 1) | (r1 >> 63); - let r1 = r1 << 1; - - let mut carry = 0; - let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); - let r1 = ::ff::adc(r1, 0, &mut carry); - let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); - let r3 = ::ff::adc(r3, 0, &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); - let r5 = ::ff::adc(r5, 0, &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); - let r7 = ::ff::adc(r7, 0, &mut carry); - let r8 = ::ff::mac_with_carry(r8, (self.0).0[4], (self.0).0[4], &mut carry); - let r9 = ::ff::adc(r9, 0, &mut carry); - let r10 = ::ff::mac_with_carry(r10, (self.0).0[5], (self.0).0[5], &mut carry); - let r11 = ::ff::adc(r11, 0, &mut carry); - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11); - } -} - -impl Fq { - /// Determines if the element is really in the field. This is only used - /// internally. - #[inline(always)] - fn is_valid(&self) -> bool { - self.0 < MODULUS - } - - /// Subtracts the modulus from this element if this element is not in the - /// field. Only used internally. - #[inline(always)] - fn reduce(&mut self) { - if !self.is_valid() { - self.0.sub_noborrow(&MODULUS); - } - } - - #[inline(always)] - fn mont_reduce( - &mut self, - r0: u64, - mut r1: u64, - mut r2: u64, - mut r3: u64, - mut r4: u64, - mut r5: u64, - mut r6: u64, - mut r7: u64, - mut r8: u64, - mut r9: u64, - mut r10: u64, - mut r11: u64, - ) { - // The Montgomery reduction here is based on Algorithm 14.32 in - // Handbook of Applied Cryptography - // . - - let k = r0.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); - r1 = ::ff::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); - r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[4], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[5], &mut carry); - r6 = ::ff::adc(r6, 0, &mut carry); - let carry2 = carry; - let k = r1.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); - r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[4], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[5], &mut carry); - r7 = ::ff::adc(r7, carry2, &mut carry); - let carry2 = carry; - let k = r2.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[4], &mut carry); - r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[5], &mut carry); - r8 = ::ff::adc(r8, carry2, &mut carry); - let carry2 = carry; - let k = r3.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); - r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[4], &mut carry); - r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[5], &mut carry); - r9 = ::ff::adc(r9, carry2, &mut carry); - let carry2 = carry; - let k = r4.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r4, k, MODULUS.0[0], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[1], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[2], &mut carry); - r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[3], &mut carry); - r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[4], &mut carry); - r9 = ::ff::mac_with_carry(r9, k, MODULUS.0[5], &mut carry); - r10 = ::ff::adc(r10, carry2, &mut carry); - let carry2 = carry; - let k = r5.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r5, k, MODULUS.0[0], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[1], &mut carry); - r7 = ::ff::mac_with_carry(r7, k, MODULUS.0[2], &mut carry); - r8 = ::ff::mac_with_carry(r8, k, MODULUS.0[3], &mut carry); - r9 = ::ff::mac_with_carry(r9, k, MODULUS.0[4], &mut carry); - r10 = ::ff::mac_with_carry(r10, k, MODULUS.0[5], &mut carry); - r11 = ::ff::adc(r11, carry2, &mut carry); - (self.0).0[0] = r6; - (self.0).0[1] = r7; - (self.0).0[2] = r8; - (self.0).0[3] = r9; - (self.0).0[4] = r10; - (self.0).0[5] = r11; - self.reduce(); - } -} - -impl SqrtField for Fq { - fn legendre(&self) -> ::ff::LegendreSymbol { - // s = self^((q - 1) // 2) - let s = self.pow([ - 0xdcff7fffffffd555, - 0xf55ffff58a9ffff, - 0xb39869507b587b12, - 0xb23ba5c279c2895f, - 0x258dd3db21a5d66b, - 0xd0088f51cbff34d, - ]); - if s == Fq::zero() { - ::ff::LegendreSymbol::Zero - } else if s == Fq::one() { - ::ff::LegendreSymbol::QuadraticResidue - } else { - ::ff::LegendreSymbol::QuadraticNonResidue - } - } - - fn sqrt(&self) -> Option { - // Shank's algorithm for q mod 4 = 3 - // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2) - - // a1 = self^((q - 3) // 4) - let mut a1 = self.pow([ - 0xee7fbfffffffeaaa, - 0x7aaffffac54ffff, - 0xd9cc34a83dac3d89, - 0xd91dd2e13ce144af, - 0x92c6e9ed90d2eb35, - 0x680447a8e5ff9a6, - ]); - let mut a0 = a1; - a0.square(); - a0.mul_assign(self); - - if a0 == NEGATIVE_ONE { - None - } else { - a1.mul_assign(self); - Some(a1) - } - } -} - #[test] fn test_b_coeff() { assert_eq!(Fq::from_repr(FqRepr::from(4)).unwrap(), B_COEFF); @@ -1897,6 +1177,8 @@ use rand::{Rand, SeedableRng, XorShiftRng}; #[test] fn test_fq_repr_ordering() { + use std::cmp::Ordering; + fn assert_equality(a: FqRepr, b: FqRepr) { assert_eq!(a, b); assert!(a.cmp(&b) == Ordering::Equal); @@ -2743,6 +2025,8 @@ fn test_fq_pow() { #[test] fn test_fq_sqrt() { + use ff::SqrtField; + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); assert_eq!(Fq::zero().sqrt().unwrap(), Fq::zero()); @@ -2876,6 +2160,8 @@ fn test_fq_num_bits() { #[test] fn test_fq_root_of_unity() { + use ff::SqrtField; + assert_eq!(Fq::S, 1); assert_eq!( Fq::multiplicative_generator(), @@ -2923,6 +2209,7 @@ fn fq_repr_tests() { #[test] fn test_fq_legendre() { use ff::LegendreSymbol::*; + use ff::SqrtField; assert_eq!(QuadraticResidue, Fq::one().legendre()); assert_eq!(Zero, Fq::zero().legendre()); diff --git a/src/bls12_381/fr.rs b/src/bls12_381/fr.rs index e9eee24f3..6e142f093 100644 --- a/src/bls12_381/fr.rs +++ b/src/bls12_381/fr.rs @@ -1,646 +1,10 @@ -use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; +use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; -// r = 52435875175126190479447740508185965837690552500527637822603658699938581184513 -const MODULUS: FrRepr = FrRepr([ - 0xffffffff00000001, - 0x53bda402fffe5bfe, - 0x3339d80809a1d805, - 0x73eda753299d7d48, -]); - -// The number of bits needed to represent the modulus. -const MODULUS_BITS: u32 = 255; - -// The number of bits that must be shaved from the beginning of -// the representation when randomly sampling. -const REPR_SHAVE_BITS: u32 = 1; - -// R = 2**256 % r -const R: FrRepr = FrRepr([ - 0x1fffffffe, - 0x5884b7fa00034802, - 0x998c4fefecbc4ff5, - 0x1824b159acc5056f, -]); - -// R2 = R^2 % r -const R2: FrRepr = FrRepr([ - 0xc999e990f3f29c6d, - 0x2b6cedcb87925c23, - 0x5d314967254398f, - 0x748d9d99f59ff11, -]); - -// INV = -(r^{-1} mod 2^64) mod 2^64 -const INV: u64 = 0xfffffffeffffffff; - -// GENERATOR = 7 (multiplicative generator of r-1 order, that is also quadratic nonresidue) -const GENERATOR: FrRepr = FrRepr([ - 0xefffffff1, - 0x17e363d300189c0f, - 0xff9c57876f8457b0, - 0x351332208fc5a8c4, -]); - -// 2^s * t = MODULUS - 1 with t odd -const S: u32 = 32; - -// 2^s root of unity computed by GENERATOR^t -const ROOT_OF_UNITY: FrRepr = FrRepr([ - 0xb9b58d8c5f0e466a, - 0x5b1b4c801819d7ec, - 0xaf53ae352a31e64, - 0x5bf3adda19e9b27b, -]); - -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] -pub struct FrRepr(pub [u64; 4]); - -impl ::rand::Rand for FrRepr { - #[inline(always)] - fn rand(rng: &mut R) -> Self { - FrRepr(rng.gen()) - } -} - -impl ::std::fmt::Display for FrRepr { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - try!(write!(f, "0x")); - for i in self.0.iter().rev() { - try!(write!(f, "{:016x}", *i)); - } - - Ok(()) - } -} - -impl AsRef<[u64]> for FrRepr { - #[inline(always)] - fn as_ref(&self) -> &[u64] { - &self.0 - } -} - -impl AsMut<[u64]> for FrRepr { - #[inline(always)] - fn as_mut(&mut self) -> &mut [u64] { - &mut self.0 - } -} - -impl From for FrRepr { - #[inline(always)] - fn from(val: u64) -> FrRepr { - let mut repr = Self::default(); - repr.0[0] = val; - repr - } -} - -impl Ord for FrRepr { - #[inline(always)] - fn cmp(&self, other: &FrRepr) -> ::std::cmp::Ordering { - for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) { - if a < b { - return ::std::cmp::Ordering::Less; - } else if a > b { - return ::std::cmp::Ordering::Greater; - } - } - - ::std::cmp::Ordering::Equal - } -} - -impl PartialOrd for FrRepr { - #[inline(always)] - fn partial_cmp(&self, other: &FrRepr) -> Option<::std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl PrimeFieldRepr for FrRepr { - #[inline(always)] - fn is_odd(&self) -> bool { - self.0[0] & 1 == 1 - } - - #[inline(always)] - fn is_even(&self) -> bool { - !self.is_odd() - } - - #[inline(always)] - fn is_zero(&self) -> bool { - self.0.iter().all(|&e| e == 0) - } - - #[inline(always)] - fn shr(&mut self, mut n: u32) { - if n >= 64 * 4 { - *self = Self::from(0); - return; - } - - while n >= 64 { - let mut t = 0; - for i in self.0.iter_mut().rev() { - ::std::mem::swap(&mut t, i); - } - n -= 64; - } - - if n > 0 { - let mut t = 0; - for i in self.0.iter_mut().rev() { - let t2 = *i << (64 - n); - *i >>= n; - *i |= t; - t = t2; - } - } - } - - #[inline(always)] - fn div2(&mut self) { - let mut t = 0; - for i in self.0.iter_mut().rev() { - let t2 = *i << 63; - *i >>= 1; - *i |= t; - t = t2; - } - } - - #[inline(always)] - fn mul2(&mut self) { - let mut last = 0; - for i in &mut self.0 { - let tmp = *i >> 63; - *i <<= 1; - *i |= last; - last = tmp; - } - } - - #[inline(always)] - fn shl(&mut self, mut n: u32) { - if n >= 64 * 4 { - *self = Self::from(0); - return; - } - - while n >= 64 { - let mut t = 0; - for i in &mut self.0 { - ::std::mem::swap(&mut t, i); - } - n -= 64; - } - - if n > 0 { - let mut t = 0; - for i in &mut self.0 { - let t2 = *i >> (64 - n); - *i <<= n; - *i |= t; - t = t2; - } - } - } - - #[inline(always)] - fn num_bits(&self) -> u32 { - let mut ret = (4 as u32) * 64; - for i in self.0.iter().rev() { - let leading = i.leading_zeros(); - ret -= leading; - if leading != 64 { - break; - } - } - - ret - } - - #[inline(always)] - fn add_nocarry(&mut self, other: &FrRepr) { - let mut carry = 0; - - for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::ff::adc(*a, *b, &mut carry); - } - } - - #[inline(always)] - fn sub_noborrow(&mut self, other: &FrRepr) { - let mut borrow = 0; - - for (a, b) in self.0.iter_mut().zip(other.0.iter()) { - *a = ::ff::sbb(*a, *b, &mut borrow); - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(PrimeField)] +#[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] +#[PrimeFieldGenerator = "7"] pub struct Fr(FrRepr); -impl ::std::fmt::Display for Fr { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "Fr({})", self.into_repr()) - } -} - -impl ::rand::Rand for Fr { - fn rand(rng: &mut R) -> Self { - loop { - let mut tmp = Fr(FrRepr::rand(rng)); - - // Mask away the unused bits at the beginning. - tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; - - if tmp.is_valid() { - return tmp; - } - } - } -} - -impl From for FrRepr { - fn from(e: Fr) -> FrRepr { - e.into_repr() - } -} - -impl PrimeField for Fr { - type Repr = FrRepr; - - fn from_repr(r: FrRepr) -> Result { - let mut r = Fr(r); - if r.is_valid() { - r.mul_assign(&Fr(R2)); - - Ok(r) - } else { - Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0))) - } - } - - fn into_repr(&self) -> FrRepr { - let mut r = *self; - r.mont_reduce( - (self.0).0[0], - (self.0).0[1], - (self.0).0[2], - (self.0).0[3], - 0, - 0, - 0, - 0, - ); - r.0 - } - - fn char() -> FrRepr { - MODULUS - } - - const NUM_BITS: u32 = MODULUS_BITS; - - const CAPACITY: u32 = Self::NUM_BITS - 1; - - fn multiplicative_generator() -> Self { - Fr(GENERATOR) - } - - const S: u32 = S; - - fn root_of_unity() -> Self { - Fr(ROOT_OF_UNITY) - } -} - -impl Field for Fr { - #[inline] - fn zero() -> Self { - Fr(FrRepr::from(0)) - } - - #[inline] - fn one() -> Self { - Fr(R) - } - - #[inline] - fn is_zero(&self) -> bool { - self.0.is_zero() - } - - #[inline] - fn add_assign(&mut self, other: &Fr) { - // This cannot exceed the backing capacity. - self.0.add_nocarry(&other.0); - - // However, it may need to be reduced. - self.reduce(); - } - - #[inline] - fn double(&mut self) { - // This cannot exceed the backing capacity. - self.0.mul2(); - - // However, it may need to be reduced. - self.reduce(); - } - - #[inline] - fn sub_assign(&mut self, other: &Fr) { - // If `other` is larger than `self`, we'll need to add the modulus to self first. - if other.0 > self.0 { - self.0.add_nocarry(&MODULUS); - } - - self.0.sub_noborrow(&other.0); - } - - #[inline] - fn negate(&mut self) { - if !self.is_zero() { - let mut tmp = MODULUS; - tmp.sub_noborrow(&self.0); - self.0 = tmp; - } - } - - fn inverse(&self) -> Option { - if self.is_zero() { - None - } else { - // Guajardo Kumar Paar Pelzl - // Efficient Software-Implementation of Finite Fields with Applications to Cryptography - // Algorithm 16 (BEA for Inversion in Fp) - - let one = FrRepr::from(1); - - let mut u = self.0; - let mut v = MODULUS; - let mut b = Fr(R2); // Avoids unnecessary reduction step. - let mut c = Self::zero(); - - while u != one && v != one { - while u.is_even() { - u.div2(); - - if b.0.is_even() { - b.0.div2(); - } else { - b.0.add_nocarry(&MODULUS); - b.0.div2(); - } - } - - while v.is_even() { - v.div2(); - - if c.0.is_even() { - c.0.div2(); - } else { - c.0.add_nocarry(&MODULUS); - c.0.div2(); - } - } - - if v < u { - u.sub_noborrow(&v); - b.sub_assign(&c); - } else { - v.sub_noborrow(&u); - c.sub_assign(&b); - } - } - - if u == one { - Some(b) - } else { - Some(c) - } - } - } - - #[inline(always)] - fn frobenius_map(&mut self, _: usize) { - // This has no effect in a prime field. - } - - #[inline] - fn mul_assign(&mut self, other: &Fr) { - let mut carry = 0; - let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); - let r4 = carry; - let mut carry = 0; - let r1 = ::ff::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); - let r5 = carry; - let mut carry = 0; - let r2 = ::ff::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = ::ff::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); - let r6 = carry; - let mut carry = 0; - let r3 = ::ff::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = ::ff::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); - let r7 = carry; - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); - } - - #[inline] - fn square(&mut self) { - let mut carry = 0; - let r1 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); - let r2 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); - let r3 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); - let r4 = carry; - let mut carry = 0; - let r3 = ::ff::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); - let r5 = carry; - let mut carry = 0; - let r5 = ::ff::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); - let r6 = carry; - - let r7 = r6 >> 63; - let r6 = (r6 << 1) | (r5 >> 63); - let r5 = (r5 << 1) | (r4 >> 63); - let r4 = (r4 << 1) | (r3 >> 63); - let r3 = (r3 << 1) | (r2 >> 63); - let r2 = (r2 << 1) | (r1 >> 63); - let r1 = r1 << 1; - - let mut carry = 0; - let r0 = ::ff::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); - let r1 = ::ff::adc(r1, 0, &mut carry); - let r2 = ::ff::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); - let r3 = ::ff::adc(r3, 0, &mut carry); - let r4 = ::ff::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); - let r5 = ::ff::adc(r5, 0, &mut carry); - let r6 = ::ff::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); - let r7 = ::ff::adc(r7, 0, &mut carry); - self.mont_reduce(r0, r1, r2, r3, r4, r5, r6, r7); - } -} - -impl Fr { - /// Determines if the element is really in the field. This is only used - /// internally. - #[inline(always)] - fn is_valid(&self) -> bool { - self.0 < MODULUS - } - - /// Subtracts the modulus from this element if this element is not in the - /// field. Only used internally. - #[inline(always)] - fn reduce(&mut self) { - if !self.is_valid() { - self.0.sub_noborrow(&MODULUS); - } - } - - #[inline(always)] - fn mont_reduce( - &mut self, - r0: u64, - mut r1: u64, - mut r2: u64, - mut r3: u64, - mut r4: u64, - mut r5: u64, - mut r6: u64, - mut r7: u64, - ) { - // The Montgomery reduction here is based on Algorithm 14.32 in - // Handbook of Applied Cryptography - // . - - let k = r0.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); - r1 = ::ff::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); - r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); - r4 = ::ff::adc(r4, 0, &mut carry); - let carry2 = carry; - let k = r1.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); - r2 = ::ff::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); - r5 = ::ff::adc(r5, carry2, &mut carry); - let carry2 = carry; - let k = r2.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); - r3 = ::ff::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); - r6 = ::ff::adc(r6, carry2, &mut carry); - let carry2 = carry; - let k = r3.wrapping_mul(INV); - let mut carry = 0; - ::ff::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); - r4 = ::ff::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); - r5 = ::ff::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); - r6 = ::ff::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); - r7 = ::ff::adc(r7, carry2, &mut carry); - (self.0).0[0] = r4; - (self.0).0[1] = r5; - (self.0).0[2] = r6; - (self.0).0[3] = r7; - self.reduce(); - } -} - -impl SqrtField for Fr { - fn legendre(&self) -> ::ff::LegendreSymbol { - // s = self^((r - 1) // 2) - let s = self.pow([ - 0x7fffffff80000000, - 0xa9ded2017fff2dff, - 0x199cec0404d0ec02, - 0x39f6d3a994cebea4, - ]); - if s == Self::zero() { - ::ff::LegendreSymbol::Zero - } else if s == Self::one() { - ::ff::LegendreSymbol::QuadraticResidue - } else { - ::ff::LegendreSymbol::QuadraticNonResidue - } - } - - fn sqrt(&self) -> Option { - // Tonelli-Shank's algorithm for q mod 16 = 1 - // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) - match self.legendre() { - ::ff::LegendreSymbol::Zero => Some(*self), - ::ff::LegendreSymbol::QuadraticNonResidue => None, - ::ff::LegendreSymbol::QuadraticResidue => { - let mut c = Fr(ROOT_OF_UNITY); - // r = self^((t + 1) // 2) - let mut r = self.pow([ - 0x7fff2dff80000000, - 0x4d0ec02a9ded201, - 0x94cebea4199cec04, - 0x39f6d3a9, - ]); - // t = self^t - let mut t = self.pow([ - 0xfffe5bfeffffffff, - 0x9a1d80553bda402, - 0x299d7d483339d808, - 0x73eda753, - ]); - let mut m = S; - - while t != Self::one() { - let mut i = 1; - { - let mut t2i = t; - t2i.square(); - loop { - if t2i == Self::one() { - break; - } - t2i.square(); - i += 1; - } - } - - for _ in 0..(m - i - 1) { - c.square(); - } - r.mul_assign(&c); - c.square(); - t.mul_assign(&c); - m = i; - } - - Some(r) - } - } - } -} - #[cfg(test)] use rand::{Rand, SeedableRng, XorShiftRng}; @@ -909,6 +273,7 @@ fn test_fr_repr_sub_noborrow() { #[test] fn test_fr_legendre() { use ff::LegendreSymbol::*; + use ff::SqrtField; assert_eq!(QuadraticResidue, Fr::one().legendre()); assert_eq!(Zero, Fr::zero().legendre()); @@ -1418,6 +783,8 @@ fn test_fr_pow() { #[test] fn test_fr_sqrt() { + use ff::SqrtField; + let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); assert_eq!(Fr::zero().sqrt().unwrap(), Fr::zero()); @@ -1583,6 +950,8 @@ fn test_fr_num_bits() { #[test] fn test_fr_root_of_unity() { + use ff::SqrtField; + assert_eq!(Fr::S, 32); assert_eq!( Fr::multiplicative_generator(), diff --git a/src/lib.rs b/src/lib.rs index 0c336ed05..fefdae338 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ #![deny(missing_debug_implementations)] extern crate byteorder; +#[macro_use] extern crate ff; extern crate rand;