diff --git a/Cargo.toml b/Cargo.toml index 4d8b37c..195b107 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ license = "MIT/Apache-2.0" repository = "https://github.com/ebfull/ff" [dependencies] +byteorder = "1" rand = "0.3" ff_derive = { version = "0.2.0", path = "ff_derive" } diff --git a/src/lib.rs b/src/lib.rs index 8bdecc7..541fe76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ -#![feature(i128_type)] #![allow(unused_imports)] +extern crate byteorder; extern crate rand; #[macro_use] @@ -8,11 +8,13 @@ extern crate ff_derive; pub use ff_derive::*; +use std::error::Error; use std::fmt; +use std::io::{self, Read, Write}; /// This trait represents an element of a field. pub trait Field: - Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + 'static + rand::Rand + 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; @@ -53,8 +55,15 @@ pub trait Field: fn pow>(&self, exp: S) -> Self { let mut res = Self::one(); + let mut found_one = false; + for i in BitIterator::new(exp) { - res.square(); + if found_one { + res.square(); + } else { + found_one = i; + } + if i { res.mul_assign(self); } @@ -66,6 +75,9 @@ pub trait Field: /// 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; @@ -82,19 +94,23 @@ pub trait PrimeFieldRepr: + Ord + Send + Sync + + Default + fmt::Debug + + fmt::Display + 'static + rand::Rand + AsRef<[u64]> + + AsMut<[u64]> + From { - /// Subtract another reprensetation from this one, returning the borrow bit. - fn sub_noborrow(&mut self, other: &Self) -> bool; + /// Subtract another represetation from this one. + fn sub_noborrow(&mut self, other: &Self); - /// Add another representation to this one, returning the carry bit. - fn add_nocarry(&mut self, other: &Self) -> bool; + /// Add another representation to this one. + fn add_nocarry(&mut self, other: &Self); - /// Compute the number of bits needed to encode this number. + /// 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. @@ -110,57 +126,179 @@ pub trait PrimeFieldRepr: /// 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) + } + } + } } /// 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; + 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; + fn from_repr(Self::Repr) -> Result; - /// Convert a biginteger reprensentation into a prime field element, if + /// 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; - /// Returns how many bits are needed to represent an element of this - /// field. - fn num_bits() -> u32; + /// How many bits are needed to represent an element of this field. + const NUM_BITS: u32; - /// Returns how many bits of information can be reliably stored in the - /// field element. - fn capacity() -> 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; - /// Returns s such that 2^s * t = `char()` - 1 with t odd. - fn s() -> usize; + /// 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 { - fn new(t: E) -> Self { + pub fn new(t: E) -> Self { let n = t.as_ref().len() * 64; - BitIterator { t: t, n: n } + BitIterator { t, n } } }