diff --git a/pairing/Cargo.toml b/pairing/Cargo.toml index 98725aa..5f16018 100644 --- a/pairing/Cargo.toml +++ b/pairing/Cargo.toml @@ -3,7 +3,10 @@ name = "pairing" # Remember to change version string in README.md. version = "0.14.2" -authors = ["Sean Bowe "] +authors = [ + "Sean Bowe ", + "Jack Grigg ", +] license = "MIT/Apache-2.0" description = "Pairing-friendly elliptic curve library" @@ -14,10 +17,9 @@ repository = "https://github.com/ebfull/pairing" [dependencies] rand = "0.4" byteorder = "1" -clippy = { version = "0.0.200", optional = true } +ff = { version = "0.4", features = ["derive"] } [features] unstable-features = ["expose-arith"] expose-arith = [] -u128-support = [] default = [] diff --git a/pairing/README.md b/pairing/README.md index d71d0c5..bf386de 100644 --- a/pairing/README.md +++ b/pairing/README.md @@ -6,14 +6,6 @@ This is a Rust crate for using pairing-friendly elliptic curves. Currently, only Bring the `pairing` crate into your project just as you normally would. -If you're using a supported platform and the nightly Rust compiler, you can enable the `u128-support` feature for faster arithmetic. - -```toml -[dependencies.pairing] -version = "0.14" -features = ["u128-support"] -``` - ## Security Warnings This library does not make any guarantees about constant-time operations, memory access patterns, or resistance to side-channel attacks. diff --git a/pairing/benches/bls12_381/fq.rs b/pairing/benches/bls12_381/fq.rs index af4dba4..053a10c 100644 --- a/pairing/benches/bls12_381/fq.rs +++ b/pairing/benches/bls12_381/fq.rs @@ -1,7 +1,7 @@ use rand::{Rand, SeedableRng, XorShiftRng}; +use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; -use pairing::{Field, PrimeField, PrimeFieldRepr, SqrtField}; #[bench] fn bench_fq_repr_add_nocarry(b: &mut ::test::Bencher) { diff --git a/pairing/benches/bls12_381/fq12.rs b/pairing/benches/bls12_381/fq12.rs index 226b850..84daca2 100644 --- a/pairing/benches/bls12_381/fq12.rs +++ b/pairing/benches/bls12_381/fq12.rs @@ -1,7 +1,7 @@ use rand::{Rand, SeedableRng, XorShiftRng}; +use ff::Field; use pairing::bls12_381::*; -use pairing::Field; #[bench] fn bench_fq12_add_assign(b: &mut ::test::Bencher) { diff --git a/pairing/benches/bls12_381/fq2.rs b/pairing/benches/bls12_381/fq2.rs index ec26e98..521b6ab 100644 --- a/pairing/benches/bls12_381/fq2.rs +++ b/pairing/benches/bls12_381/fq2.rs @@ -1,7 +1,7 @@ use rand::{Rand, SeedableRng, XorShiftRng}; +use ff::{Field, SqrtField}; use pairing::bls12_381::*; -use pairing::{Field, SqrtField}; #[bench] fn bench_fq2_add_assign(b: &mut ::test::Bencher) { diff --git a/pairing/benches/bls12_381/fr.rs b/pairing/benches/bls12_381/fr.rs index 7278629..13b0d0e 100644 --- a/pairing/benches/bls12_381/fr.rs +++ b/pairing/benches/bls12_381/fr.rs @@ -1,7 +1,7 @@ use rand::{Rand, SeedableRng, XorShiftRng}; +use ff::{Field, PrimeField, PrimeFieldRepr, SqrtField}; use pairing::bls12_381::*; -use pairing::{Field, PrimeField, PrimeFieldRepr, SqrtField}; #[bench] fn bench_fr_repr_add_nocarry(b: &mut ::test::Bencher) { diff --git a/pairing/benches/pairing_benches.rs b/pairing/benches/pairing_benches.rs index 424c4e7..af32a8a 100644 --- a/pairing/benches/pairing_benches.rs +++ b/pairing/benches/pairing_benches.rs @@ -1,5 +1,6 @@ #![feature(test)] +extern crate ff; extern crate pairing; extern crate rand; extern crate test; diff --git a/pairing/src/bls12_381/ec.rs b/pairing/src/bls12_381/ec.rs index 5cd5091..37fcbba 100644 --- a/pairing/src/bls12_381/ec.rs +++ b/pairing/src/bls12_381/ec.rs @@ -623,12 +623,10 @@ macro_rules! curve_impl { pub mod g1 { use super::super::{Bls12, Fq, Fq12, FqRepr, Fr, FrRepr}; use super::g2::G2Affine; + use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; use rand::{Rand, Rng}; use std::fmt; - use { - BitIterator, CurveAffine, CurveProjective, EncodedPoint, Engine, Field, GroupDecodingError, - PrimeField, PrimeFieldRepr, SqrtField, - }; + use {CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError}; curve_impl!( "G1", @@ -1270,12 +1268,10 @@ pub mod g1 { pub mod g2 { use super::super::{Bls12, Fq, Fq12, Fq2, FqRepr, Fr, FrRepr}; use super::g1::G1Affine; + use ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, SqrtField}; use rand::{Rand, Rng}; use std::fmt; - use { - BitIterator, CurveAffine, CurveProjective, EncodedPoint, Engine, Field, GroupDecodingError, - PrimeField, PrimeFieldRepr, SqrtField, - }; + use {CurveAffine, CurveProjective, EncodedPoint, Engine, GroupDecodingError}; curve_impl!( "G2", diff --git a/pairing/src/bls12_381/fq.rs b/pairing/src/bls12_381/fq.rs index 738da38..fd0d416 100644 --- a/pairing/src/bls12_381/fq.rs +++ b/pairing/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 ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; // B coefficient of BLS12-381 curve, 4. pub const B_COEFF: Fq = Fq(FqRepr([ @@ -507,669 +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 = ::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 = ::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 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); - let r4 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[4], &mut carry); - let r5 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[5], &mut carry); - let r6 = carry; - let mut carry = 0; - let r1 = ::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = ::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = ::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[1], (other.0).0[4], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[1], (other.0).0[5], &mut carry); - let r7 = carry; - let mut carry = 0; - let r2 = ::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = ::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[2], (other.0).0[4], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[2], (other.0).0[5], &mut carry); - let r8 = carry; - let mut carry = 0; - let r3 = ::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[3], (other.0).0[3], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[3], (other.0).0[4], &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[3], (other.0).0[5], &mut carry); - let r9 = carry; - let mut carry = 0; - let r4 = ::mac_with_carry(r4, (self.0).0[4], (other.0).0[0], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[4], (other.0).0[1], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[4], (other.0).0[2], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[4], (other.0).0[3], &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[4], (other.0).0[4], &mut carry); - let r9 = ::mac_with_carry(r9, (self.0).0[4], (other.0).0[5], &mut carry); - let r10 = carry; - let mut carry = 0; - let r5 = ::mac_with_carry(r5, (self.0).0[5], (other.0).0[0], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[5], (other.0).0[1], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[5], (other.0).0[2], &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[5], (other.0).0[3], &mut carry); - let r9 = ::mac_with_carry(r9, (self.0).0[5], (other.0).0[4], &mut carry); - let r10 = ::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 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); - let r2 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); - let r3 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); - let r4 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[4], &mut carry); - let r5 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[5], &mut carry); - let r6 = carry; - let mut carry = 0; - let r3 = ::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[1], (self.0).0[4], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[1], (self.0).0[5], &mut carry); - let r7 = carry; - let mut carry = 0; - let r5 = ::mac_with_carry(r5, (self.0).0[2], (self.0).0[3], &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[2], (self.0).0[4], &mut carry); - let r7 = ::mac_with_carry(r7, (self.0).0[2], (self.0).0[5], &mut carry); - let r8 = carry; - let mut carry = 0; - let r7 = ::mac_with_carry(r7, (self.0).0[3], (self.0).0[4], &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[3], (self.0).0[5], &mut carry); - let r9 = carry; - let mut carry = 0; - let r9 = ::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 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); - let r1 = ::adc(r1, 0, &mut carry); - let r2 = ::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); - let r3 = ::adc(r3, 0, &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); - let r5 = ::adc(r5, 0, &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); - let r7 = ::adc(r7, 0, &mut carry); - let r8 = ::mac_with_carry(r8, (self.0).0[4], (self.0).0[4], &mut carry); - let r9 = ::adc(r9, 0, &mut carry); - let r10 = ::mac_with_carry(r10, (self.0).0[5], (self.0).0[5], &mut carry); - let r11 = ::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; - ::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); - r1 = ::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); - r2 = ::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[4], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[5], &mut carry); - r6 = ::adc(r6, 0, &mut carry); - let carry2 = carry; - let k = r1.wrapping_mul(INV); - let mut carry = 0; - ::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); - r2 = ::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[4], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[5], &mut carry); - r7 = ::adc(r7, carry2, &mut carry); - let carry2 = carry; - let k = r2.wrapping_mul(INV); - let mut carry = 0; - ::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[4], &mut carry); - r7 = ::mac_with_carry(r7, k, MODULUS.0[5], &mut carry); - r8 = ::adc(r8, carry2, &mut carry); - let carry2 = carry; - let k = r3.wrapping_mul(INV); - let mut carry = 0; - ::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); - r7 = ::mac_with_carry(r7, k, MODULUS.0[4], &mut carry); - r8 = ::mac_with_carry(r8, k, MODULUS.0[5], &mut carry); - r9 = ::adc(r9, carry2, &mut carry); - let carry2 = carry; - let k = r4.wrapping_mul(INV); - let mut carry = 0; - ::mac_with_carry(r4, k, MODULUS.0[0], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[1], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[2], &mut carry); - r7 = ::mac_with_carry(r7, k, MODULUS.0[3], &mut carry); - r8 = ::mac_with_carry(r8, k, MODULUS.0[4], &mut carry); - r9 = ::mac_with_carry(r9, k, MODULUS.0[5], &mut carry); - r10 = ::adc(r10, carry2, &mut carry); - let carry2 = carry; - let k = r5.wrapping_mul(INV); - let mut carry = 0; - ::mac_with_carry(r5, k, MODULUS.0[0], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[1], &mut carry); - r7 = ::mac_with_carry(r7, k, MODULUS.0[2], &mut carry); - r8 = ::mac_with_carry(r8, k, MODULUS.0[3], &mut carry); - r9 = ::mac_with_carry(r9, k, MODULUS.0[4], &mut carry); - r10 = ::mac_with_carry(r10, k, MODULUS.0[5], &mut carry); - r11 = ::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) -> ::LegendreSymbol { - use LegendreSymbol::*; - - // s = self^((q - 1) // 2) - let s = self.pow([ - 0xdcff7fffffffd555, - 0xf55ffff58a9ffff, - 0xb39869507b587b12, - 0xb23ba5c279c2895f, - 0x258dd3db21a5d66b, - 0xd0088f51cbff34d, - ]); - if s == Fq::zero() { - Zero - } else if s == Fq::one() { - QuadraticResidue - } else { - 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); @@ -1899,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); @@ -2304,14 +1584,16 @@ fn test_fq_is_valid() { 0x17c8be1800b9f059 ])).is_valid() ); - assert!(!Fq(FqRepr([ - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff - ])).is_valid()); + assert!( + !Fq(FqRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff + ])).is_valid() + ); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); @@ -2745,6 +2027,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()); @@ -2878,6 +2162,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(), @@ -2924,7 +2210,8 @@ fn fq_repr_tests() { #[test] fn test_fq_legendre() { - use LegendreSymbol::*; + use ff::LegendreSymbol::*; + use ff::SqrtField; assert_eq!(QuadraticResidue, Fq::one().legendre()); assert_eq!(Zero, Fq::zero().legendre()); diff --git a/pairing/src/bls12_381/fq12.rs b/pairing/src/bls12_381/fq12.rs index 2bec0b1..b24fcaa 100644 --- a/pairing/src/bls12_381/fq12.rs +++ b/pairing/src/bls12_381/fq12.rs @@ -1,8 +1,8 @@ use super::fq::FROBENIUS_COEFF_FQ12_C1; use super::fq2::Fq2; use super::fq6::Fq6; +use ff::Field; use rand::{Rand, Rng}; -use Field; /// An element of Fq12, represented by c0 + c1 * w. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -182,7 +182,7 @@ fn test_fq12_mul_by_014() { #[test] fn fq12_field_tests() { - use PrimeField; + use ff::PrimeField; ::tests::field::random_field_tests::(); ::tests::field::random_frobenius_tests::(super::fq::Fq::char(), 13); diff --git a/pairing/src/bls12_381/fq2.rs b/pairing/src/bls12_381/fq2.rs index 18cd580..363439a 100644 --- a/pairing/src/bls12_381/fq2.rs +++ b/pairing/src/bls12_381/fq2.rs @@ -1,6 +1,6 @@ use super::fq::{FROBENIUS_COEFF_FQ2_C1, Fq, NEGATIVE_ONE}; +use ff::{Field, SqrtField}; use rand::{Rand, Rng}; -use {Field, SqrtField}; use std::cmp::Ordering; @@ -160,7 +160,7 @@ impl Field for Fq2 { } impl SqrtField for Fq2 { - fn legendre(&self) -> ::LegendreSymbol { + fn legendre(&self) -> ::ff::LegendreSymbol { self.norm().legendre() } @@ -263,16 +263,18 @@ fn test_fq2_basics() { ); assert!(Fq2::zero().is_zero()); assert!(!Fq2::one().is_zero()); - assert!(!Fq2 { - c0: Fq::zero(), - c1: Fq::one(), - }.is_zero()); + assert!( + !Fq2 { + c0: Fq::zero(), + c1: Fq::one(), + }.is_zero() + ); } #[test] fn test_fq2_squaring() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::one(), @@ -346,7 +348,7 @@ fn test_fq2_squaring() { #[test] fn test_fq2_mul() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -410,7 +412,7 @@ fn test_fq2_mul() { #[test] fn test_fq2_inverse() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; assert!(Fq2::zero().inverse().is_none()); @@ -459,7 +461,7 @@ fn test_fq2_inverse() { #[test] fn test_fq2_addition() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -523,7 +525,7 @@ fn test_fq2_addition() { #[test] fn test_fq2_subtraction() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -587,7 +589,7 @@ fn test_fq2_subtraction() { #[test] fn test_fq2_negation() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -634,7 +636,7 @@ fn test_fq2_negation() { #[test] fn test_fq2_doubling() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -681,7 +683,7 @@ fn test_fq2_doubling() { #[test] fn test_fq2_frobenius_map() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; let mut a = Fq2 { c0: Fq::from_repr(FqRepr([ @@ -794,7 +796,7 @@ fn test_fq2_frobenius_map() { #[test] fn test_fq2_sqrt() { use super::fq::FqRepr; - use PrimeField; + use ff::PrimeField; assert_eq!( Fq2 { @@ -865,7 +867,7 @@ fn test_fq2_sqrt() { #[test] fn test_fq2_legendre() { - use LegendreSymbol::*; + use ff::LegendreSymbol::*; assert_eq!(Zero, Fq2::zero().legendre()); // i^2 = -1 @@ -900,7 +902,7 @@ fn test_fq2_mul_nonresidue() { #[test] fn fq2_field_tests() { - use PrimeField; + use ff::PrimeField; ::tests::field::random_field_tests::(); ::tests::field::random_sqrt_tests::(); diff --git a/pairing/src/bls12_381/fq6.rs b/pairing/src/bls12_381/fq6.rs index c065f27..36c6e28 100644 --- a/pairing/src/bls12_381/fq6.rs +++ b/pairing/src/bls12_381/fq6.rs @@ -1,7 +1,7 @@ use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2}; use super::fq2::Fq2; +use ff::Field; use rand::{Rand, Rng}; -use Field; /// An element of Fq6, represented by c0 + c1 * v + c2 * v^(2). #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -367,7 +367,7 @@ fn test_fq6_mul_by_01() { #[test] fn fq6_field_tests() { - use PrimeField; + use ff::PrimeField; ::tests::field::random_field_tests::(); ::tests::field::random_frobenius_tests::(super::fq::Fq::char(), 13); diff --git a/pairing/src/bls12_381/fr.rs b/pairing/src/bls12_381/fr.rs index 4e9d6ab..5e57631 100644 --- a/pairing/src/bls12_381/fr.rs +++ b/pairing/src/bls12_381/fr.rs @@ -1,647 +1,10 @@ -use LegendreSymbol::*; -use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField}; - -// 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)) - } -} +use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr}; -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 = ::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 = ::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 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); - let r1 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); - let r2 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[2], &mut carry); - let r3 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[3], &mut carry); - let r4 = carry; - let mut carry = 0; - let r1 = ::mac_with_carry(r1, (self.0).0[1], (other.0).0[0], &mut carry); - let r2 = ::mac_with_carry(r2, (self.0).0[1], (other.0).0[1], &mut carry); - let r3 = ::mac_with_carry(r3, (self.0).0[1], (other.0).0[2], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[1], (other.0).0[3], &mut carry); - let r5 = carry; - let mut carry = 0; - let r2 = ::mac_with_carry(r2, (self.0).0[2], (other.0).0[0], &mut carry); - let r3 = ::mac_with_carry(r3, (self.0).0[2], (other.0).0[1], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[2], (other.0).0[2], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[2], (other.0).0[3], &mut carry); - let r6 = carry; - let mut carry = 0; - let r3 = ::mac_with_carry(r3, (self.0).0[3], (other.0).0[0], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[3], (other.0).0[1], &mut carry); - let r5 = ::mac_with_carry(r5, (self.0).0[3], (other.0).0[2], &mut carry); - let r6 = ::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 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); - let r2 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); - let r3 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[3], &mut carry); - let r4 = carry; - let mut carry = 0; - let r3 = ::mac_with_carry(r3, (self.0).0[1], (self.0).0[2], &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[1], (self.0).0[3], &mut carry); - let r5 = carry; - let mut carry = 0; - let r5 = ::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 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[0], &mut carry); - let r1 = ::adc(r1, 0, &mut carry); - let r2 = ::mac_with_carry(r2, (self.0).0[1], (self.0).0[1], &mut carry); - let r3 = ::adc(r3, 0, &mut carry); - let r4 = ::mac_with_carry(r4, (self.0).0[2], (self.0).0[2], &mut carry); - let r5 = ::adc(r5, 0, &mut carry); - let r6 = ::mac_with_carry(r6, (self.0).0[3], (self.0).0[3], &mut carry); - let r7 = ::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; - ::mac_with_carry(r0, k, MODULUS.0[0], &mut carry); - r1 = ::mac_with_carry(r1, k, MODULUS.0[1], &mut carry); - r2 = ::mac_with_carry(r2, k, MODULUS.0[2], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[3], &mut carry); - r4 = ::adc(r4, 0, &mut carry); - let carry2 = carry; - let k = r1.wrapping_mul(INV); - let mut carry = 0; - ::mac_with_carry(r1, k, MODULUS.0[0], &mut carry); - r2 = ::mac_with_carry(r2, k, MODULUS.0[1], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[2], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[3], &mut carry); - r5 = ::adc(r5, carry2, &mut carry); - let carry2 = carry; - let k = r2.wrapping_mul(INV); - let mut carry = 0; - ::mac_with_carry(r2, k, MODULUS.0[0], &mut carry); - r3 = ::mac_with_carry(r3, k, MODULUS.0[1], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[2], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[3], &mut carry); - r6 = ::adc(r6, carry2, &mut carry); - let carry2 = carry; - let k = r3.wrapping_mul(INV); - let mut carry = 0; - ::mac_with_carry(r3, k, MODULUS.0[0], &mut carry); - r4 = ::mac_with_carry(r4, k, MODULUS.0[1], &mut carry); - r5 = ::mac_with_carry(r5, k, MODULUS.0[2], &mut carry); - r6 = ::mac_with_carry(r6, k, MODULUS.0[3], &mut carry); - r7 = ::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) -> ::LegendreSymbol { - // s = self^((r - 1) // 2) - let s = self.pow([ - 0x7fffffff80000000, - 0xa9ded2017fff2dff, - 0x199cec0404d0ec02, - 0x39f6d3a994cebea4, - ]); - if s == Self::zero() { - Zero - } else if s == Self::one() { - QuadraticResidue - } else { - 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() { - Zero => Some(*self), - QuadraticNonResidue => None, - 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 +272,9 @@ 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()); @@ -1022,12 +388,14 @@ fn test_fr_is_valid() { 0x73eda753299d7d48 ])).is_valid() ); - assert!(!Fr(FrRepr([ - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff, - 0xffffffffffffffff - ])).is_valid()); + assert!( + !Fr(FrRepr([ + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff, + 0xffffffffffffffff + ])).is_valid() + ); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); @@ -1417,6 +785,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()); @@ -1582,6 +952,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/pairing/src/bls12_381/mod.rs b/pairing/src/bls12_381/mod.rs index a5db4b5..106591e 100644 --- a/pairing/src/bls12_381/mod.rs +++ b/pairing/src/bls12_381/mod.rs @@ -18,7 +18,9 @@ pub use self::fq2::Fq2; pub use self::fq6::Fq6; pub use self::fr::{Fr, FrRepr}; -use super::{BitIterator, CurveAffine, Engine, Field}; +use super::{CurveAffine, Engine}; + +use ff::{BitIterator, Field, ScalarEngine}; // The BLS parameter x for BLS12-381 is -0xd201000000010000 const BLS_X: u64 = 0xd201000000010000; @@ -27,8 +29,11 @@ const BLS_X_IS_NEGATIVE: bool = true; #[derive(Clone, Debug)] pub struct Bls12; -impl Engine for Bls12 { +impl ScalarEngine for Bls12 { type Fr = Fr; +} + +impl Engine for Bls12 { type G1 = G1; type G1Affine = G1Affine; type G2 = G2; diff --git a/pairing/src/lib.rs b/pairing/src/lib.rs index 08365f1..bbced76 100644 --- a/pairing/src/lib.rs +++ b/pairing/src/lib.rs @@ -1,19 +1,19 @@ // `clippy` is a code linting tool for improving code quality by catching -// common mistakes or strange code patterns. If the `clippy` feature is -// provided, it is enabled and all compiler warnings are prohibited. -#![cfg_attr(feature = "clippy", deny(warnings))] -#![cfg_attr(feature = "clippy", feature(plugin))] -#![cfg_attr(feature = "clippy", plugin(clippy))] -#![cfg_attr(feature = "clippy", allow(inline_always))] -#![cfg_attr(feature = "clippy", allow(too_many_arguments))] -#![cfg_attr(feature = "clippy", allow(unreadable_literal))] -#![cfg_attr(feature = "clippy", allow(many_single_char_names))] -#![cfg_attr(feature = "clippy", allow(new_without_default_derive))] -#![cfg_attr(feature = "clippy", allow(write_literal))] +// common mistakes or strange code patterns. If the `cargo-clippy` feature +// is provided, all compiler warnings are prohibited. +#![cfg_attr(feature = "cargo-clippy", deny(warnings))] +#![cfg_attr(feature = "cargo-clippy", allow(inline_always))] +#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] +#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))] +#![cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))] +#![cfg_attr(feature = "cargo-clippy", allow(new_without_default_derive))] +#![cfg_attr(feature = "cargo-clippy", allow(write_literal))] // Force public structures to implement Debug #![deny(missing_debug_implementations)] extern crate byteorder; +#[macro_use] +extern crate ff; extern crate rand; #[cfg(test)] @@ -24,17 +24,14 @@ pub mod bls12_381; mod wnaf; pub use self::wnaf::Wnaf; +use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField}; use std::error::Error; use std::fmt; -use std::io::{self, Read, Write}; /// An "engine" is a collection of types (fields, elliptic curve groups, etc.) /// with well-defined relationships. In particular, the G1/G2 curve groups are /// of prime order `r`, and are equipped with a bilinear pairing function. -pub trait Engine: Sized + 'static + Clone { - /// This is the scalar field of the G1/G2 groups. - type Fr: PrimeField + SqrtField; - +pub trait Engine: ScalarEngine { /// The projective representation of an element in G1. type G1: CurveProjective< Engine = Self, @@ -263,208 +260,6 @@ pub trait EncodedPoint: fn from_affine(affine: Self::Affine) -> Self; } -/// This trait represents an element of a field. -pub trait Field: - Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + rand::Rand -{ - /// Returns the zero element of the field, the additive identity. - fn zero() -> Self; - - /// Returns the one element of the field, the multiplicative identity. - fn one() -> Self; - - /// Returns true iff this element is zero. - fn is_zero(&self) -> bool; - - /// Squares this element. - fn square(&mut self); - - /// Doubles this element. - fn double(&mut self); - - /// Negates this element. - fn negate(&mut self); - - /// Adds another element to this element. - fn add_assign(&mut self, other: &Self); - - /// Subtracts another element from this element. - fn sub_assign(&mut self, other: &Self); - - /// Multiplies another element by this element. - fn mul_assign(&mut self, other: &Self); - - /// Computes the multiplicative inverse of this element, if nonzero. - fn inverse(&self) -> Option; - - /// Exponentiates this element by a power of the base prime modulus via - /// the Frobenius automorphism. - fn frobenius_map(&mut self, power: usize); - - /// Exponentiates this element by a number represented with `u64` limbs, - /// least significant digit first. - fn pow>(&self, exp: S) -> Self { - let mut res = Self::one(); - - let mut found_one = false; - - for i in BitIterator::new(exp) { - if found_one { - res.square(); - } else { - found_one = i; - } - - if i { - res.mul_assign(self); - } - } - - res - } -} - -/// This trait represents an element of a field that has a square root operation described for it. -pub trait SqrtField: Field { - /// Returns the Legendre symbol of the field element. - fn legendre(&self) -> LegendreSymbol; - - /// Returns the square root of the field element, if it is - /// quadratic residue. - fn sqrt(&self) -> Option; -} - -/// This trait represents a wrapper around a biginteger which can encode any element of a particular -/// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit -/// first. -pub trait PrimeFieldRepr: - Sized - + Copy - + Clone - + Eq - + Ord - + Send - + Sync - + Default - + fmt::Debug - + fmt::Display - + 'static - + rand::Rand - + AsRef<[u64]> - + AsMut<[u64]> - + From -{ - /// Subtract another represetation from this one. - fn sub_noborrow(&mut self, other: &Self); - - /// Add another representation to this one. - fn add_nocarry(&mut self, other: &Self); - - /// Compute the number of bits needed to encode this number. Always a - /// multiple of 64. - fn num_bits(&self) -> u32; - - /// Returns true iff this number is zero. - fn is_zero(&self) -> bool; - - /// Returns true iff this number is odd. - fn is_odd(&self) -> bool; - - /// Returns true iff this number is even. - fn is_even(&self) -> bool; - - /// Performs a rightwise bitshift of this number, effectively dividing - /// it by 2. - fn div2(&mut self); - - /// Performs a rightwise bitshift of this number by some amount. - fn shr(&mut self, amt: u32); - - /// Performs a leftwise bitshift of this number, effectively multiplying - /// it by 2. Overflow is ignored. - fn mul2(&mut self); - - /// Performs a leftwise bitshift of this number by some amount. - fn shl(&mut self, amt: u32); - - /// Writes this `PrimeFieldRepr` as a big endian integer. - fn write_be(&self, mut writer: W) -> io::Result<()> { - use byteorder::{BigEndian, WriteBytesExt}; - - for digit in self.as_ref().iter().rev() { - writer.write_u64::(*digit)?; - } - - Ok(()) - } - - /// Reads a big endian integer into this representation. - fn read_be(&mut self, mut reader: R) -> io::Result<()> { - use byteorder::{BigEndian, ReadBytesExt}; - - for digit in self.as_mut().iter_mut().rev() { - *digit = reader.read_u64::()?; - } - - Ok(()) - } - - /// Writes this `PrimeFieldRepr` as a little endian integer. - fn write_le(&self, mut writer: W) -> io::Result<()> { - use byteorder::{LittleEndian, WriteBytesExt}; - - for digit in self.as_ref().iter() { - writer.write_u64::(*digit)?; - } - - Ok(()) - } - - /// Reads a little endian integer into this representation. - fn read_le(&mut self, mut reader: R) -> io::Result<()> { - use byteorder::{LittleEndian, ReadBytesExt}; - - for digit in self.as_mut().iter_mut() { - *digit = reader.read_u64::()?; - } - - Ok(()) - } -} - -#[derive(Debug, PartialEq)] -pub enum LegendreSymbol { - Zero = 0, - QuadraticResidue = 1, - QuadraticNonResidue = -1, -} - -/// An error that may occur when trying to interpret a `PrimeFieldRepr` as a -/// `PrimeField` element. -#[derive(Debug)] -pub enum PrimeFieldDecodingError { - /// The encoded value is not in the field - NotInField(String), -} - -impl Error for PrimeFieldDecodingError { - fn description(&self) -> &str { - match *self { - PrimeFieldDecodingError::NotInField(..) => "not an element of the field", - } - } -} - -impl fmt::Display for PrimeFieldDecodingError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - PrimeFieldDecodingError::NotInField(ref repr) => { - write!(f, "{} is not an element of the field", repr) - } - } - } -} - /// An error that may occur when trying to decode an `EncodedPoint`. #[derive(Debug)] pub enum GroupDecodingError { @@ -504,255 +299,3 @@ impl fmt::Display for GroupDecodingError { } } } - -/// This represents an element of a prime field. -pub trait PrimeField: Field { - /// The prime field can be converted back and forth into this biginteger - /// representation. - type Repr: PrimeFieldRepr + From; - - /// Interpret a string of numbers as a (congruent) prime field element. - /// Does not accept unnecessary leading zeroes or a blank string. - fn from_str(s: &str) -> Option { - if s.is_empty() { - return None; - } - - if s == "0" { - return Some(Self::zero()); - } - - let mut res = Self::zero(); - - let ten = Self::from_repr(Self::Repr::from(10)).unwrap(); - - let mut first_digit = true; - - for c in s.chars() { - match c.to_digit(10) { - Some(c) => { - if first_digit { - if c == 0 { - return None; - } - - first_digit = false; - } - - res.mul_assign(&ten); - res.add_assign(&Self::from_repr(Self::Repr::from(u64::from(c))).unwrap()); - } - None => { - return None; - } - } - } - - Some(res) - } - - /// Convert this prime field element into a biginteger representation. - fn from_repr(Self::Repr) -> Result; - - /// Convert a biginteger representation into a prime field element, if - /// the number is an element of the field. - fn into_repr(&self) -> Self::Repr; - - /// Returns the field characteristic; the modulus. - fn char() -> Self::Repr; - - /// How many bits are needed to represent an element of this field. - const NUM_BITS: u32; - - /// How many bits of information can be reliably stored in the field element. - const CAPACITY: u32; - - /// Returns the multiplicative generator of `char()` - 1 order. This element - /// must also be quadratic nonresidue. - fn multiplicative_generator() -> Self; - - /// 2^s * t = `char()` - 1 with t odd. - const S: u32; - - /// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()` - /// by t. - fn root_of_unity() -> Self; -} - -#[derive(Debug)] -pub struct BitIterator { - t: E, - n: usize, -} - -impl> BitIterator { - pub fn new(t: E) -> Self { - let n = t.as_ref().len() * 64; - - BitIterator { t, n } - } -} - -impl> Iterator for BitIterator { - type Item = bool; - - fn next(&mut self) -> Option { - if self.n == 0 { - None - } else { - self.n -= 1; - let part = self.n / 64; - let bit = self.n - (64 * part); - - Some(self.t.as_ref()[part] & (1 << bit) > 0) - } - } -} - -#[test] -fn test_bit_iterator() { - let mut a = BitIterator::new([0xa953d79b83f6ab59, 0x6dea2059e200bd39]); - let expected = "01101101111010100010000001011001111000100000000010111101001110011010100101010011110101111001101110000011111101101010101101011001"; - - for e in expected.chars() { - assert!(a.next().unwrap() == (e == '1')); - } - - assert!(a.next().is_none()); - - let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001"; - - let mut a = BitIterator::new([ - 0x429d5f3ac3a3b759, - 0xb10f4c66768b1c92, - 0x92368b6d16ecd3b4, - 0xa57ea85ae8775219, - ]); - - for e in expected.chars() { - assert!(a.next().unwrap() == (e == '1')); - } - - assert!(a.next().is_none()); -} - -#[cfg(not(feature = "expose-arith"))] -use self::arith_impl::*; - -#[cfg(feature = "expose-arith")] -pub use self::arith_impl::*; - -#[cfg(feature = "u128-support")] -mod arith_impl { - /// Calculate a - b - borrow, returning the result and modifying - /// the borrow value. - #[inline(always)] - pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 { - let tmp = (1u128 << 64) + u128::from(a) - u128::from(b) - u128::from(*borrow); - - *borrow = if tmp >> 64 == 0 { 1 } else { 0 }; - - tmp as u64 - } - - /// Calculate a + b + carry, returning the sum and modifying the - /// carry value. - #[inline(always)] - pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 { - let tmp = u128::from(a) + u128::from(b) + u128::from(*carry); - - *carry = (tmp >> 64) as u64; - - tmp as u64 - } - - /// Calculate a + (b * c) + carry, returning the least significant digit - /// and setting carry to the most significant digit. - #[inline(always)] - pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 { - let tmp = (u128::from(a)) + u128::from(b) * u128::from(c) + u128::from(*carry); - - *carry = (tmp >> 64) as u64; - - tmp as u64 - } -} - -#[cfg(not(feature = "u128-support"))] -mod arith_impl { - #[inline(always)] - fn split_u64(i: u64) -> (u64, u64) { - (i >> 32, i & 0xFFFFFFFF) - } - - #[inline(always)] - fn combine_u64(hi: u64, lo: u64) -> u64 { - (hi << 32) | lo - } - - /// Calculate a - b - borrow, returning the result and modifying - /// the borrow value. - #[inline(always)] - pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 { - let (a_hi, a_lo) = split_u64(a); - let (b_hi, b_lo) = split_u64(b); - let (b, r0) = split_u64((1 << 32) + a_lo - b_lo - *borrow); - let (b, r1) = split_u64((1 << 32) + a_hi - b_hi - ((b == 0) as u64)); - - *borrow = (b == 0) as u64; - - combine_u64(r1, r0) - } - - /// Calculate a + b + carry, returning the sum and modifying the - /// carry value. - #[inline(always)] - pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 { - let (a_hi, a_lo) = split_u64(a); - let (b_hi, b_lo) = split_u64(b); - let (carry_hi, carry_lo) = split_u64(*carry); - - let (t, r0) = split_u64(a_lo + b_lo + carry_lo); - let (t, r1) = split_u64(t + a_hi + b_hi + carry_hi); - - *carry = t; - - combine_u64(r1, r0) - } - - /// Calculate a + (b * c) + carry, returning the least significant digit - /// and setting carry to the most significant digit. - #[inline(always)] - pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 { - /* - [ b_hi | b_lo ] - [ c_hi | c_lo ] * - ------------------------------------------- - [ b_lo * c_lo ] <-- w - [ b_hi * c_lo ] <-- x - [ b_lo * c_hi ] <-- y - [ b_hi * c_lo ] <-- z - [ a_hi | a_lo ] - [ C_hi | C_lo ] - */ - - let (a_hi, a_lo) = split_u64(a); - let (b_hi, b_lo) = split_u64(b); - let (c_hi, c_lo) = split_u64(c); - let (carry_hi, carry_lo) = split_u64(*carry); - - let (w_hi, w_lo) = split_u64(b_lo * c_lo); - let (x_hi, x_lo) = split_u64(b_hi * c_lo); - let (y_hi, y_lo) = split_u64(b_lo * c_hi); - let (z_hi, z_lo) = split_u64(b_hi * c_hi); - - let (t, r0) = split_u64(w_lo + a_lo + carry_lo); - let (t, r1) = split_u64(t + w_hi + x_lo + y_lo + a_hi + carry_hi); - let (t, r2) = split_u64(t + x_hi + y_hi + z_lo); - let (_, r3) = split_u64(t + z_hi); - - *carry = combine_u64(r3, r2); - - combine_u64(r1, r0) - } -} diff --git a/pairing/src/tests/curve.rs b/pairing/src/tests/curve.rs index 1480b74..bb0406c 100644 --- a/pairing/src/tests/curve.rs +++ b/pairing/src/tests/curve.rs @@ -1,6 +1,7 @@ +use ff::Field; use rand::{Rand, Rng, SeedableRng, XorShiftRng}; -use {CurveAffine, CurveProjective, EncodedPoint, Field}; +use {CurveAffine, CurveProjective, EncodedPoint}; pub fn curve_tests() { let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); @@ -66,8 +67,8 @@ pub fn curve_tests() { } fn random_wnaf_tests() { + use ff::PrimeField; use wnaf::*; - use PrimeField; let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); diff --git a/pairing/src/tests/field.rs b/pairing/src/tests/field.rs index 74422fd..55396a7 100644 --- a/pairing/src/tests/field.rs +++ b/pairing/src/tests/field.rs @@ -1,5 +1,5 @@ +use ff::{Field, LegendreSymbol, PrimeField, SqrtField}; use rand::{Rng, SeedableRng, XorShiftRng}; -use {Field, LegendreSymbol, PrimeField, SqrtField}; pub fn random_frobenius_tests>(characteristic: C, maxpower: usize) { let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); diff --git a/pairing/src/tests/repr.rs b/pairing/src/tests/repr.rs index 681a476..09dd441 100644 --- a/pairing/src/tests/repr.rs +++ b/pairing/src/tests/repr.rs @@ -1,5 +1,5 @@ +use ff::PrimeFieldRepr; use rand::{SeedableRng, XorShiftRng}; -use PrimeFieldRepr; pub fn random_repr_tests() { random_encoding_tests::();