diff --git a/Cargo.toml b/Cargo.toml index 98725aa..dcf7c32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ repository = "https://github.com/ebfull/pairing" rand = "0.4" byteorder = "1" clippy = { version = "0.0.200", optional = true } +ff = "0.3" [features] unstable-features = ["expose-arith"] diff --git a/benches/bls12_381/fq.rs b/benches/bls12_381/fq.rs index af4dba4..053a10c 100644 --- a/benches/bls12_381/fq.rs +++ b/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/benches/bls12_381/fq12.rs b/benches/bls12_381/fq12.rs index 226b850..84daca2 100644 --- a/benches/bls12_381/fq12.rs +++ b/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/benches/bls12_381/fq2.rs b/benches/bls12_381/fq2.rs index ec26e98..521b6ab 100644 --- a/benches/bls12_381/fq2.rs +++ b/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/benches/bls12_381/fr.rs b/benches/bls12_381/fr.rs index 7278629..13b0d0e 100644 --- a/benches/bls12_381/fr.rs +++ b/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/benches/pairing_benches.rs b/benches/pairing_benches.rs index 424c4e7..af32a8a 100644 --- a/benches/pairing_benches.rs +++ b/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/src/lib.rs b/src/lib.rs index 08365f1..effc050 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ #![deny(missing_debug_implementations)] extern crate byteorder; +extern crate ff; extern crate rand; #[cfg(test)] @@ -24,9 +25,9 @@ pub mod bls12_381; mod wnaf; pub use self::wnaf::Wnaf; +use ff::*; 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 @@ -263,208 +264,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 +303,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) - } -}