diff --git a/Cargo.toml b/Cargo.toml index 225504ab..f2281f90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ name = "api" rand = "0.4" rustc-serialize = { version = "0.3", optional = true } byteorder = "1.0" +crunchy = "0.2.1" [dev-dependencies.bincode] version = "0.6" diff --git a/benches/api.rs b/benches/api.rs index 8340eaac..de5b5b0a 100644 --- a/benches/api.rs +++ b/benches/api.rs @@ -1,12 +1,12 @@ #![feature(test)] -extern crate test; -extern crate rand; -extern crate bn; extern crate bincode; +extern crate bn; +extern crate rand; +extern crate test; use bn::*; use bincode::SizeLimit::Infinite; -use bincode::rustc_serialize::{encode, decode}; +use bincode::rustc_serialize::{decode, encode}; const SAMPLES: usize = 30; @@ -17,17 +17,15 @@ macro_rules! benchmark( let $rng = &mut rand::thread_rng(); let $input: Vec<_> = (0..SAMPLES).map(|_| $pre).collect(); - b.bench_n(SAMPLES as u64, |b| { - let mut c = 0; + let mut c = 0; - b.iter(|| { - c += 1; + b.iter(|| { + c += 1; - let $input = &$input[c % SAMPLES]; + let $input = &$input[c % SAMPLES]; - $post - }) - }) + $post + }); } ) ); diff --git a/src/arith.rs b/src/arith.rs index b1fecf2a..a1d5614b 100644 --- a/src/arith.rs +++ b/src/arith.rs @@ -2,8 +2,8 @@ use std::cmp::Ordering; use rand::Rng; #[cfg(feature = "rustc-serialize")] -use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; -use byteorder::{ByteOrder, BigEndian}; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use byteorder::{BigEndian, ByteOrder}; /// 256-bit, stack allocated biginteger for use in prime field /// arithmetic. @@ -22,20 +22,30 @@ impl U512 { pub fn from(c1: &U256, c0: &U256, modulo: &U256) -> U512 { let mut res = [0; 8]; - for (i, xi) in c1.0.iter().enumerate() { - mac_digit(&mut res[i..], &modulo.0, *xi); + debug_assert_eq!(c1.0.len(), 4); + unroll! { + for i in 0..4 { + mac_digit(i, &mut res, &modulo.0, c1.0[i]); + } } - let mut c0_iter = c0.0.iter(); let mut carry = 0; - for ai in res.iter_mut() { - if let Some(bi) = c0_iter.next() { - *ai = adc(*ai, *bi, &mut carry); - } else if carry != 0 { - *ai = adc(*ai, 0, &mut carry); - } else { - break; + debug_assert_eq!(res.len(), 8); + unroll! { + for i in 0..4 { + res[i] = adc(res[i], c0.0[i], &mut carry); + } + } + + unroll! { + for i in 0..4 { + let (a1, a0) = split_u64(res[i + 4]); + let (c, r0) = split_u64(a0 + carry); + let (c, r1) = split_u64(a1 + c); + carry = c; + + res[i + 4] = combine_u64(r1, r0); } } @@ -45,8 +55,7 @@ impl U512 { } /// Get a random U512 - pub fn random(rng: &mut R) -> U512 - { + pub fn random(rng: &mut R) -> U512 { U512(rng.gen()) } @@ -63,8 +72,7 @@ impl U512 { /// Divides self by modulo, returning remainder and, if /// possible, a quotient smaller than the modulus. - pub fn divrem(&self, modulo: &U256) -> (Option, U256) - { + pub fn divrem(&self, modulo: &U256) -> (Option, U256) { let mut q = Some(U256::zero()); let mut r = U256::zero(); @@ -154,7 +162,7 @@ impl Decodable for U256 { buf[i] = try!(s.read_u8()); } - U256::from_slice(&buf).map_err(|_| s.error("Invalid input length; Also unreachable;")) + U256::from_slice(&buf).map_err(|_| s.error("Invalid input length; Also unreachable;")) } } @@ -187,10 +195,14 @@ pub enum Error { } impl U256 { - /// Initialize U256 from slice of bytes (big endian) pub fn from_slice(s: &[u8]) -> Result { - if s.len() != 32 { return Err(Error::InvalidLength { expected: 32, actual: s.len() }); } + if s.len() != 32 { + return Err(Error::InvalidLength { + expected: 32, + actual: s.len(), + }); + } let mut n = [0; 4]; for (l, i) in (0..4).rev().zip((0..4).map(|i| i * 8)) { @@ -201,11 +213,16 @@ impl U256 { } pub fn to_big_endian(&self, s: &mut [u8]) -> Result<(), Error> { - if s.len() != 32 { return Err(Error::InvalidLength { expected: 32, actual: s.len() }); } + if s.len() != 32 { + return Err(Error::InvalidLength { + expected: 32, + actual: s.len(), + }); + } for (l, i) in (0..4).rev().zip((0..4).map(|i| i * 8)) { BigEndian::write_u64(&mut s[i..], self.0[l]); - } + } Ok(()) } @@ -221,20 +238,15 @@ impl U256 { } /// Produce a random number (mod `modulo`) - pub fn random(rng: &mut R, modulo: &U256) -> U256 - { + pub fn random(rng: &mut R, modulo: &U256) -> U256 { U512::random(rng).divrem(modulo).1 } pub fn is_zero(&self) -> bool { - self.0[0] == 0 && - self.0[1] == 0 && - self.0[2] == 0 && - self.0[3] == 0 + self.0[0] == 0 && self.0[1] == 0 && self.0[2] == 0 && self.0[3] == 0 } - pub fn set_bit(&mut self, n: usize, to: bool) -> bool - { + pub fn set_bit(&mut self, n: usize, to: bool) -> bool { if n >= 256 { false } else { @@ -251,8 +263,7 @@ impl U256 { } } - pub fn get_bit(&self, n: usize) -> Option - { + pub fn get_bit(&self, n: usize) -> Option { if n >= 256 { None } else { @@ -296,7 +307,7 @@ impl U256 { if *self > Self::zero() { let mut tmp = modulo.0; sub_noborrow(&mut tmp, &self.0); - + self.0 = tmp; } } @@ -358,16 +369,13 @@ impl U256 { /// Return an Iterator over all bits from /// MSB to LSB. pub fn bits(&self) -> BitIterator { - BitIterator { - int: &self, - n: 256 - } + BitIterator { int: &self, n: 256 } } } pub struct BitIterator<'a> { int: &'a U256, - n: usize + n: usize, } impl<'a> Iterator for BitIterator<'a> { @@ -376,8 +384,7 @@ impl<'a> Iterator for BitIterator<'a> { fn next(&mut self) -> Option { if self.n == 0 { None - } - else { + } else { self.n -= 1; self.int.get_bit(self.n) @@ -467,8 +474,9 @@ fn sub_noborrow(a: &mut [u64; 4], b: &[u64; 4]) { debug_assert!(0 == borrow); } -fn mac_digit(acc: &mut [u64], b: &[u64], c: u64) -{ +// TODO: Make `from_index` a const param +#[inline(always)] +fn mac_digit(from_index: usize, acc: &mut [u64; 8], b: &[u64; 4], c: u64) { #[inline] fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 { let (b_hi, b_lo) = split_u64(b); @@ -479,7 +487,8 @@ fn mac_digit(acc: &mut [u64], b: &[u64], c: u64) let (x_hi, x_lo) = split_u64(b_lo * c_lo + a_lo + carry_lo); let (y_hi, y_lo) = split_u64(b_lo * c_hi); let (z_hi, z_lo) = split_u64(b_hi * c_lo); - let (r_hi, r_lo) = split_u64(x_hi + y_lo + z_lo + a_hi + carry_hi); + // Brackets to allow better ILP + let (r_hi, r_lo) = split_u64((x_hi + y_lo) + (z_lo + a_hi) + carry_hi); *carry = (b_hi * c_hi) + r_hi + y_hi + z_hi; @@ -490,16 +499,28 @@ fn mac_digit(acc: &mut [u64], b: &[u64], c: u64) return; } - let mut b_iter = b.iter(); let mut carry = 0; - for ai in acc.iter_mut() { - if let Some(bi) = b_iter.next() { - *ai = mac_with_carry(*ai, *bi, c, &mut carry); - } else if carry != 0 { - *ai = mac_with_carry(*ai, 0, c, &mut carry); - } else { - break; + debug_assert_eq!(acc.len(), 8); + unroll! { + for i in 0..4 { + let a_index = i + from_index; + acc[a_index] = mac_with_carry(acc[a_index], b[i], c, &mut carry); + } + } + unroll! { + for i in 0..4 { + let a_index = i + from_index + 4; + if a_index < 8 { + let (a_hi, a_lo) = split_u64(acc[a_index]); + let (carry_hi, carry_lo) = split_u64(carry); + let (x_hi, x_lo) = split_u64(a_lo + carry_lo); + let (r_hi, r_lo) = split_u64(x_hi + a_hi + carry_hi); + + carry = r_hi; + + acc[a_index] = combine_u64(r_lo, x_lo); + } } } @@ -507,25 +528,23 @@ fn mac_digit(acc: &mut [u64], b: &[u64], c: u64) } #[inline] -fn mul_reduce( - this: &mut [u64; 4], - by: &[u64; 4], - modulus: &[u64; 4], - inv: u64 -) -{ +fn mul_reduce(this: &mut [u64; 4], by: &[u64; 4], modulus: &[u64; 4], inv: u64) { // The Montgomery reduction here is based on Algorithm 14.32 in // Handbook of Applied Cryptography // . - let mut res = [0; 2*4]; - for (i, xi) in this.iter().enumerate() { - mac_digit(&mut res[i..], by, *xi); + let mut res = [0; 2 * 4]; + unroll! { + for i in 0..4 { + mac_digit(i, &mut res, by, this[i]); + } } - for i in 0..4 { - let k = inv.wrapping_mul(res[i]); - mac_digit(&mut res[i..], modulus, k); + unroll! { + for i in 0..4 { + let k = inv.wrapping_mul(res[i]); + mac_digit(i, &mut res, modulus, k); + } } this.copy_from_slice(&res[4..]); @@ -551,7 +570,8 @@ fn from_slice() { let mut s = [0u8; 32]; s[31] = 1; - let num = U256::from_slice(&s).expect("U256 should initialize ok from slice in `from_slice` test"); + let num = + U256::from_slice(&s).expect("U256 should initialize ok from slice in `from_slice` test"); assert_eq!(num, tst); } @@ -560,12 +580,13 @@ fn to_big_endian() { let num = U256::one(); let mut s = [0u8; 32]; - num.to_big_endian(&mut s).expect("U256 should convert to bytes ok in `to_big_endian` test"); + num.to_big_endian(&mut s) + .expect("U256 should convert to bytes ok in `to_big_endian` test"); assert_eq!( s, [ - 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, ] ); } @@ -574,7 +595,12 @@ fn to_big_endian() { fn testing_divrem() { let rng = &mut ::rand::thread_rng(); - let modulo = U256([0x3c208c16d87cfd47, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029]); + let modulo = U256([ + 0x3c208c16d87cfd47, + 0x97816a916871ca8d, + 0xb85045b68181585d, + 0x30644e72e131a029, + ]); for _ in 0..100 { let c0 = U256::random(rng, &modulo); @@ -598,7 +624,7 @@ fn testing_divrem() { 0, 0, 0, - 0 + 0, ]); let (c1, c0) = a.divrem(&modulo); @@ -616,12 +642,28 @@ fn testing_divrem() { 0x26edfa5c34c6b38d, 0xb00b855116375606, 0x599a6f7c0348d21c, - 0x0925c4b8763cbf9c + 0x0925c4b8763cbf9c, ]); let (c1, c0) = a.divrem(&modulo); - assert_eq!(c1.unwrap(), U256([0x3c208c16d87cfd46, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029])); - assert_eq!(c0, U256([0x3c208c16d87cfd46, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029])); + assert_eq!( + c1.unwrap(), + U256([ + 0x3c208c16d87cfd46, + 0x97816a916871ca8d, + 0xb85045b68181585d, + 0x30644e72e131a029 + ]) + ); + assert_eq!( + c0, + U256([ + 0x3c208c16d87cfd46, + 0x97816a916871ca8d, + 0xb85045b68181585d, + 0x30644e72e131a029 + ]) + ); } { @@ -634,13 +676,29 @@ fn testing_divrem() { 0x26edfa5c34c6b38d, 0xb00b855116375606, 0x599a6f7c0348d21c, - 0x0925c4b8763cbf9c + 0x0925c4b8763cbf9c, ]); let (c1, c0) = a.divrem(&modulo); - assert_eq!(c1.unwrap(), U256([0x3c208c16d87cfd46, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029])); - assert_eq!(c0, U256([0x3c208c16d87cfd45, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029])); + assert_eq!( + c1.unwrap(), + U256([ + 0x3c208c16d87cfd46, + 0x97816a916871ca8d, + 0xb85045b68181585d, + 0x30644e72e131a029 + ]) + ); + assert_eq!( + c0, + U256([ + 0x3c208c16d87cfd45, + 0x97816a916871ca8d, + 0xb85045b68181585d, + 0x30644e72e131a029 + ]) + ); } { @@ -653,12 +711,20 @@ fn testing_divrem() { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, - 0xffffffffffffffff + 0xffffffffffffffff, ]); let (c1, c0) = a.divrem(&modulo); assert!(c1.is_none()); - assert_eq!(c0, U256([0xf32cfc5b538afa88, 0xb5e71911d44501fb, 0x47ab1eff0a417ff6, 0x06d89f71cab8351f])); + assert_eq!( + c0, + U256([ + 0xf32cfc5b538afa88, + 0xb5e71911d44501fb, + 0x47ab1eff0a417ff6, + 0x06d89f71cab8351f + ]) + ); } { @@ -671,7 +737,7 @@ fn testing_divrem() { 0x26edfa5c34c6b38d, 0xb00b855116375606, 0x599a6f7c0348d21c, - 0x0925c4b8763cbf9c + 0x0925c4b8763cbf9c, ]); let (c1, c0) = a.divrem(&modulo); @@ -689,7 +755,7 @@ fn testing_divrem() { 0x26edfa5c34c6b38d, 0xb00b855116375606, 0x599a6f7c0348d21c, - 0x0925c4b8763cbf9c + 0x0925c4b8763cbf9c, ]); let (c1, c0) = a.divrem(&modulo); @@ -698,7 +764,12 @@ fn testing_divrem() { } { - let modulo = U256([0x43e1f593f0000001, 0x2833e84879b97091, 0xb85045b68181585d, 0x30644e72e131a029]); + let modulo = U256([ + 0x43e1f593f0000001, + 0x2833e84879b97091, + 0xb85045b68181585d, + 0x30644e72e131a029, + ]); // Fr modulus masked off is valid let a = U512([ @@ -709,7 +780,7 @@ fn testing_divrem() { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, - 0x07ffffffffffffff + 0x07ffffffffffffff, ]); let (c1, c0) = a.divrem(&modulo); diff --git a/src/fields/fp.rs b/src/fields/fp.rs index 0e093edf..a746d3a2 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -1,11 +1,11 @@ use rand::Rng; -use std::ops::{Add, Sub, Mul, Neg}; +use std::ops::{Add, Mul, Neg, Sub}; use super::FieldElement; #[cfg(feature = "rustc-serialize")] -use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; -use arith::{U512, U256}; +use arith::{U256, U512}; macro_rules! field_impl { ($name:ident, $modulus:expr, $rsquared:expr, $rcubed:expr, $one:expr, $inv:expr) => { @@ -17,7 +17,7 @@ macro_rules! field_impl { #[inline] fn from(mut a: $name) -> Self { a.0.mul(&U256::one(), &U256($modulus), $inv); - + a.0 } } @@ -114,7 +114,7 @@ macro_rules! field_impl { fn one() -> Self { $name(U256($one)) } - + fn random(rng: &mut R) -> Self { $name(U256::random(rng, &U256($modulus))) } @@ -184,19 +184,59 @@ macro_rules! field_impl { field_impl!( Fr, - [0x43e1f593f0000001, 0x2833e84879b97091, 0xb85045b68181585d, 0x30644e72e131a029], - [0x1bb8e645ae216da7, 0x53fe3ab1e35c59e3, 0x8c49833d53bb8085, 0x0216d0b17f4e44a5], - [0x5e94d8e1b4bf0040, 0x2a489cbe1cfbb6b8, 0x893cc664a19fcfed, 0x0cf8594b7fcc657c], - [0xac96341c4ffffffb, 0x36fc76959f60cd29, 0x666ea36f7879462e, 0xe0a77c19a07df2f], + [ + 0x43e1f593f0000001, + 0x2833e84879b97091, + 0xb85045b68181585d, + 0x30644e72e131a029 + ], + [ + 0x1bb8e645ae216da7, + 0x53fe3ab1e35c59e3, + 0x8c49833d53bb8085, + 0x0216d0b17f4e44a5 + ], + [ + 0x5e94d8e1b4bf0040, + 0x2a489cbe1cfbb6b8, + 0x893cc664a19fcfed, + 0x0cf8594b7fcc657c + ], + [ + 0xac96341c4ffffffb, + 0x36fc76959f60cd29, + 0x666ea36f7879462e, + 0xe0a77c19a07df2f + ], 0xc2e1f593efffffff ); field_impl!( Fq, - [0x3c208c16d87cfd47, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029], - [0xf32cfc5b538afa89, 0xb5e71911d44501fb, 0x47ab1eff0a417ff6, 0x06d89f71cab8351f], - [0xb1cd6dafda1530df, 0x62f210e6a7283db6, 0xef7f0b0c0ada0afb, 0x20fd6e902d592544], - [0xd35d438dc58f0d9d, 0xa78eb28f5c70b3d, 0x666ea36f7879462c, 0xe0a77c19a07df2f], + [ + 0x3c208c16d87cfd47, + 0x97816a916871ca8d, + 0xb85045b68181585d, + 0x30644e72e131a029 + ], + [ + 0xf32cfc5b538afa89, + 0xb5e71911d44501fb, + 0x47ab1eff0a417ff6, + 0x06d89f71cab8351f + ], + [ + 0xb1cd6dafda1530df, + 0x62f210e6a7283db6, + 0xef7f0b0c0ada0afb, + 0x20fd6e902d592544 + ], + [ + 0xd35d438dc58f0d9d, + 0xa78eb28f5c70b3d, + 0x666ea36f7879462c, + 0xe0a77c19a07df2f + ], 0x87d20782e4866389 ); diff --git a/src/fields/fq12.rs b/src/fields/fq12.rs index ab2d16f4..342a591f 100644 --- a/src/fields/fq12.rs +++ b/src/fields/fq12.rs @@ -1,5 +1,5 @@ -use fields::{FieldElement, Fq2, Fq, Fq6, const_fq}; -use std::ops::{Add, Sub, Mul, Neg}; +use fields::{const_fq, FieldElement, Fq, Fq2, Fq6}; +use std::ops::{Add, Mul, Neg, Sub}; use rand::Rng; use arith::U256; @@ -8,18 +8,43 @@ fn frobenius_coeffs_c1(power: usize) -> Fq2 { match power % 12 { 0 => Fq2::one(), 1 => Fq2::new( - const_fq([12653890742059813127, 14585784200204367754, 1278438861261381767, 212598772761311868]), - const_fq([11683091849979440498, 14992204589386555739, 15866167890766973222, 1200023580730561873]) + const_fq([ + 12653890742059813127, + 14585784200204367754, + 1278438861261381767, + 212598772761311868, + ]), + const_fq([ + 11683091849979440498, + 14992204589386555739, + 15866167890766973222, + 1200023580730561873, + ]), ), 2 => Fq2::new( - const_fq([14595462726357228530, 17349508522658994025, 1017833795229664280, 299787779797702374]), - Fq::zero() + const_fq([ + 14595462726357228530, + 17349508522658994025, + 1017833795229664280, + 299787779797702374, + ]), + Fq::zero(), ), 3 => Fq2::new( - const_fq([3914496794763385213, 790120733010914719, 7322192392869644725, 581366264293887267]), - const_fq([12817045492518885689, 4440270538777280383, 11178533038884588256, 2767537931541304486]) + const_fq([ + 3914496794763385213, + 790120733010914719, + 7322192392869644725, + 581366264293887267, + ]), + const_fq([ + 12817045492518885689, + 4440270538777280383, + 11178533038884588256, + 2767537931541304486, + ]), ), - _ => unimplemented!() + _ => unimplemented!(), } } @@ -27,15 +52,12 @@ fn frobenius_coeffs_c1(power: usize) -> Fq2 { #[repr(C)] pub struct Fq12 { c0: Fq6, - c1: Fq6 + c1: Fq6, } impl Fq12 { pub fn new(c0: Fq6, c1: Fq6) -> Self { - Fq12 { - c0: c0, - c1: c1 - } + Fq12 { c0: c0, c1: c1 } } fn final_exponentiation_first_chunk(&self) -> Option { @@ -46,8 +68,8 @@ impl Fq12 { let d = c.frobenius_map(2); Some(d * c) - }, - None => None + } + None => None, } } @@ -84,30 +106,29 @@ impl Fq12 { } pub fn final_exponentiation(&self) -> Option { - self.final_exponentiation_first_chunk().map(|a| a.final_exponentiation_last_chunk()) + self.final_exponentiation_first_chunk() + .map(|a| a.final_exponentiation_last_chunk()) } pub fn frobenius_map(&self, power: usize) -> Self { Fq12 { c0: self.c0.frobenius_map(power), - c1: self.c1.frobenius_map(power).scale(frobenius_coeffs_c1(power)) + c1: self.c1 + .frobenius_map(power) + .scale(frobenius_coeffs_c1(power)), } } pub fn exp_by_neg_z(&self) -> Fq12 { - self.cyclotomic_pow( - U256([4965661367192848881, 0, 0, 0]) - ).unitary_inverse() + self.cyclotomic_pow(U256([4965661367192848881, 0, 0, 0])) + .unitary_inverse() } pub fn unitary_inverse(&self) -> Fq12 { Fq12::new(self.c0, -self.c1) } - pub fn mul_by_024(&self, - ell_0: Fq2, - ell_vw: Fq2, - ell_vv: Fq2) -> Fq12 { + pub fn mul_by_024(&self, ell_0: Fq2, ell_vw: Fq2, ell_vv: Fq2) -> Fq12 { let z0 = self.c0.c0; let z1 = self.c0.c1; let z2 = self.c0.c2; @@ -171,7 +192,7 @@ impl Fq12 { Fq12 { c0: Fq6::new(z0, z1, z2), - c1: Fq6::new(z3, z4, z5) + c1: Fq6::new(z3, z4, z5), } } @@ -222,7 +243,7 @@ impl Fq12 { Fq12 { c0: Fq6::new(z0, z4, z3), - c1: Fq6::new(z2, z1, z5) + c1: Fq6::new(z2, z1, z5), } } @@ -250,21 +271,21 @@ impl FieldElement for Fq12 { fn zero() -> Self { Fq12 { c0: Fq6::zero(), - c1: Fq6::zero() + c1: Fq6::zero(), } } fn one() -> Self { Fq12 { c0: Fq6::one(), - c1: Fq6::zero() + c1: Fq6::zero(), } } - + fn random(rng: &mut R) -> Self { Fq12 { c0: Fq6::random(rng), - c1: Fq6::random(rng) + c1: Fq6::random(rng), } } @@ -276,8 +297,9 @@ impl FieldElement for Fq12 { let ab = self.c0 * self.c1; Fq12 { - c0: (self.c1.mul_by_nonresidue() + self.c0) * (self.c0 + self.c1) - ab - ab.mul_by_nonresidue(), - c1: ab + ab + c0: (self.c1.mul_by_nonresidue() + self.c0) * (self.c0 + self.c1) - ab + - ab.mul_by_nonresidue(), + c1: ab + ab, } } @@ -285,9 +307,9 @@ impl FieldElement for Fq12 { match (self.c0.squared() - (self.c1.squared().mul_by_nonresidue())).inverse() { Some(t) => Some(Fq12 { c0: self.c0 * t, - c1: -(self.c1 * t) + c1: -(self.c1 * t), }), - None => None + None => None, } } } @@ -301,7 +323,7 @@ impl Mul for Fq12 { Fq12 { c0: bb.mul_by_nonresidue() + aa, - c1: (self.c0 + self.c1) * (other.c0 + other.c1) - aa - bb + c1: (self.c0 + self.c1) * (other.c0 + other.c1) - aa - bb, } } } @@ -312,7 +334,7 @@ impl Sub for Fq12 { fn sub(self, other: Fq12) -> Fq12 { Fq12 { c0: self.c0 - other.c0, - c1: self.c1 - other.c1 + c1: self.c1 - other.c1, } } } @@ -323,7 +345,7 @@ impl Add for Fq12 { fn add(self, other: Fq12) -> Fq12 { Fq12 { c0: self.c0 + other.c0, - c1: self.c1 + other.c1 + c1: self.c1 + other.c1, } } } @@ -334,7 +356,7 @@ impl Neg for Fq12 { fn neg(self) -> Fq12 { Fq12 { c0: -self.c0, - c1: -self.c1 + c1: -self.c1, } } } diff --git a/src/fields/fq2.rs b/src/fields/fq2.rs index d99bda7b..98a40a5c 100644 --- a/src/fields/fq2.rs +++ b/src/fields/fq2.rs @@ -1,24 +1,39 @@ -use fields::{FieldElement, const_fq, Fq}; -use std::ops::{Add, Sub, Mul, Neg}; +use fields::{const_fq, FieldElement, Fq}; +use std::ops::{Add, Mul, Neg, Sub}; use rand::Rng; use arith::{U256, U512}; #[cfg(feature = "rustc-serialize")] -use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; #[inline] fn fq_non_residue() -> Fq { // (q - 1) is a quadratic nonresidue in Fq // 21888242871839275222246405745257275088696311157297823662689037894645226208582 - const_fq([0x68c3488912edefaa, 0x8d087f6872aabf4f, 0x51e1a24709081231, 0x2259d6b14729c0fa]) + const_fq([ + 0x68c3488912edefaa, + 0x8d087f6872aabf4f, + 0x51e1a24709081231, + 0x2259d6b14729c0fa, + ]) } #[inline] pub fn fq2_nonresidue() -> Fq2 { Fq2::new( - const_fq([0xf60647ce410d7ff7, 0x2f3d6f4dd31bd011, 0x2943337e3940c6d1, 0x1d9598e8a7e39857]), - const_fq([0xd35d438dc58f0d9d, 0x0a78eb28f5c70b3d, 0x666ea36f7879462c, 0x0e0a77c19a07df2f]) + const_fq([ + 0xf60647ce410d7ff7, + 0x2f3d6f4dd31bd011, + 0x2943337e3940c6d1, + 0x1d9598e8a7e39857, + ]), + const_fq([ + 0xd35d438dc58f0d9d, + 0x0a78eb28f5c70b3d, + 0x666ea36f7879462c, + 0x0e0a77c19a07df2f, + ]), ) } @@ -26,7 +41,7 @@ pub fn fq2_nonresidue() -> Fq2 { #[repr(C)] pub struct Fq2 { c0: Fq, - c1: Fq + c1: Fq, } #[cfg(feature = "rustc-serialize")] @@ -45,28 +60,21 @@ impl Decodable for Fq2 { let combined = try!(U512::decode(s)); match combined.divrem(&Fq::modulus()) { - (Some(c1), c0) => { - Ok(Fq2::new(Fq::new(c0).unwrap(), Fq::new(c1).unwrap())) - }, - _ => { - Err(s.error("integer not less than modulus squared")) - } + (Some(c1), c0) => Ok(Fq2::new(Fq::new(c0).unwrap(), Fq::new(c1).unwrap())), + _ => Err(s.error("integer not less than modulus squared")), } } } impl Fq2 { pub fn new(c0: Fq, c1: Fq) -> Self { - Fq2 { - c0: c0, - c1: c1 - } + Fq2 { c0: c0, c1: c1 } } pub fn scale(&self, by: Fq) -> Self { Fq2 { c0: self.c0 * by, - c1: self.c1 * by + c1: self.c1 * by, } } @@ -80,7 +88,7 @@ impl Fq2 { } else { Fq2 { c0: self.c0, - c1: self.c1 * fq_non_residue() + c1: self.c1 * fq_non_residue(), } } } @@ -90,21 +98,21 @@ impl FieldElement for Fq2 { fn zero() -> Self { Fq2 { c0: Fq::zero(), - c1: Fq::zero() + c1: Fq::zero(), } } fn one() -> Self { Fq2 { c0: Fq::one(), - c1: Fq::zero() + c1: Fq::zero(), } } - + fn random(rng: &mut R) -> Self { Fq2 { c0: Fq::random(rng), - c1: Fq::random(rng) + c1: Fq::random(rng), } } @@ -120,8 +128,9 @@ impl FieldElement for Fq2 { let ab = self.c0 * self.c1; Fq2 { - c0: (self.c1 * fq_non_residue() + self.c0) * (self.c0 + self.c1) - ab - ab * fq_non_residue(), - c1: ab + ab + c0: (self.c1 * fq_non_residue() + self.c0) * (self.c0 + self.c1) - ab + - ab * fq_non_residue(), + c1: ab + ab, } } @@ -132,9 +141,9 @@ impl FieldElement for Fq2 { match (self.c0.squared() - (self.c1.squared() * fq_non_residue())).inverse() { Some(t) => Some(Fq2 { c0: self.c0 * t, - c1: -(self.c1 * t) + c1: -(self.c1 * t), }), - None => None + None => None, } } } @@ -152,7 +161,7 @@ impl Mul for Fq2 { Fq2 { c0: bb * fq_non_residue() + aa, - c1: (self.c0 + self.c1) * (other.c0 + other.c1) - aa - bb + c1: (self.c0 + self.c1) * (other.c0 + other.c1) - aa - bb, } } } @@ -163,7 +172,7 @@ impl Sub for Fq2 { fn sub(self, other: Fq2) -> Fq2 { Fq2 { c0: self.c0 - other.c0, - c1: self.c1 - other.c1 + c1: self.c1 - other.c1, } } } @@ -174,7 +183,7 @@ impl Add for Fq2 { fn add(self, other: Fq2) -> Fq2 { Fq2 { c0: self.c0 + other.c0, - c1: self.c1 + other.c1 + c1: self.c1 + other.c1, } } } @@ -185,7 +194,7 @@ impl Neg for Fq2 { fn neg(self) -> Fq2 { Fq2 { c0: -self.c0, - c1: -self.c1 + c1: -self.c1, } } } diff --git a/src/fields/fq6.rs b/src/fields/fq6.rs index ec5258fc..b4b1e0c8 100644 --- a/src/fields/fq6.rs +++ b/src/fields/fq6.rs @@ -1,41 +1,91 @@ -use fields::{FieldElement, Fq, Fq2, const_fq}; -use std::ops::{Add, Sub, Mul, Neg}; +use fields::{const_fq, FieldElement, Fq, Fq2}; +use std::ops::{Add, Mul, Neg, Sub}; use rand::Rng; fn frobenius_coeffs_c1(n: usize) -> Fq2 { match n % 6 { 0 => Fq2::one(), 1 => Fq2::new( - const_fq([13075984984163199792, 3782902503040509012, 8791150885551868305, 1825854335138010348]), - const_fq([7963664994991228759, 12257807996192067905, 13179524609921305146, 2767831111890561987]) + const_fq([ + 13075984984163199792, + 3782902503040509012, + 8791150885551868305, + 1825854335138010348, + ]), + const_fq([ + 7963664994991228759, + 12257807996192067905, + 13179524609921305146, + 2767831111890561987, + ]), ), 2 => Fq2::new( - const_fq([3697675806616062876, 9065277094688085689, 6918009208039626314, 2775033306905974752]), - Fq::zero() + const_fq([ + 3697675806616062876, + 9065277094688085689, + 6918009208039626314, + 2775033306905974752, + ]), + Fq::zero(), ), 3 => Fq2::new( - const_fq([14532872967180610477, 12903226530429559474, 1868623743233345524, 2316889217940299650]), - const_fq([12447993766991532972, 4121872836076202828, 7630813605053367399, 740282956577754197]) + const_fq([ + 14532872967180610477, + 12903226530429559474, + 1868623743233345524, + 2316889217940299650, + ]), + const_fq([ + 12447993766991532972, + 4121872836076202828, + 7630813605053367399, + 740282956577754197, + ]), ), - _ => unimplemented!() + _ => unimplemented!(), } } fn frobenius_coeffs_c2(n: usize) -> Fq2 { match n % 6 { 0 => Fq2::one(), 1 => Fq2::new( - const_fq([8314163329781907090, 11942187022798819835, 11282677263046157209, 1576150870752482284]), - const_fq([6763840483288992073, 7118829427391486816, 4016233444936635065, 2630958277570195709]) + const_fq([ + 8314163329781907090, + 11942187022798819835, + 11282677263046157209, + 1576150870752482284, + ]), + const_fq([ + 6763840483288992073, + 7118829427391486816, + 4016233444936635065, + 2630958277570195709, + ]), ), 2 => Fq2::new( - const_fq([8183898218631979349, 12014359695528440611, 12263358156045030468, 3187210487005268291]), - Fq::zero() + const_fq([ + 8183898218631979349, + 12014359695528440611, + 12263358156045030468, + 3187210487005268291, + ]), + Fq::zero(), ), 3 => Fq2::new( - const_fq([4938922280314430175, 13823286637238282975, 15589480384090068090, 481952561930628184]), - const_fq([3105754162722846417, 11647802298615474591, 13057042392041828081, 1660844386505564338]) + const_fq([ + 4938922280314430175, + 13823286637238282975, + 15589480384090068090, + 481952561930628184, + ]), + const_fq([ + 3105754162722846417, + 11647802298615474591, + 13057042392041828081, + 1660844386505564338, + ]), ), - _ => unimplemented!() + _ => unimplemented!(), } } @@ -44,7 +94,7 @@ fn frobenius_coeffs_c2(n: usize) -> Fq2 { pub struct Fq6 { pub c0: Fq2, pub c1: Fq2, - pub c2: Fq2 + pub c2: Fq2, } impl Fq6 { @@ -52,7 +102,7 @@ impl Fq6 { Fq6 { c0: c0, c1: c1, - c2: c2 + c2: c2, } } @@ -60,7 +110,7 @@ impl Fq6 { Fq6 { c0: self.c2.mul_by_nonresidue(), c1: self.c0, - c2: self.c1 + c2: self.c1, } } @@ -68,7 +118,7 @@ impl Fq6 { Fq6 { c0: self.c0 * by, c1: self.c1 * by, - c2: self.c2 * by + c2: self.c2 * by, } } @@ -76,7 +126,7 @@ impl Fq6 { Fq6 { c0: self.c0.frobenius_map(power), c1: self.c1.frobenius_map(power) * frobenius_coeffs_c1(power), - c2: self.c2.frobenius_map(power) * frobenius_coeffs_c2(power) + c2: self.c2.frobenius_map(power) * frobenius_coeffs_c2(power), } } } @@ -86,7 +136,7 @@ impl FieldElement for Fq6 { Fq6 { c0: Fq2::zero(), c1: Fq2::zero(), - c2: Fq2::zero() + c2: Fq2::zero(), } } @@ -94,15 +144,15 @@ impl FieldElement for Fq6 { Fq6 { c0: Fq2::one(), c1: Fq2::zero(), - c2: Fq2::zero() + c2: Fq2::zero(), } } - + fn random(rng: &mut R) -> Self { Fq6 { c0: Fq2::random(rng), c1: Fq2::random(rng), - c2: Fq2::random(rng) + c2: Fq2::random(rng), } } @@ -122,7 +172,7 @@ impl FieldElement for Fq6 { Fq6 { c0: s0 + s3.mul_by_nonresidue(), c1: s1 + s4.mul_by_nonresidue(), - c2: s1 + s2 + s3 - s0 - s4 + c2: s1 + s2 + s3 - s0 - s4, } } @@ -134,9 +184,9 @@ impl FieldElement for Fq6 { Some(t) => Some(Fq6 { c0: t * c0, c1: t * c1, - c2: t * c2 + c2: t * c2, }), - None => None + None => None, } } } @@ -152,7 +202,7 @@ impl Mul for Fq6 { Fq6 { c0: ((self.c1 + self.c2) * (other.c1 + other.c2) - b_b - c_c).mul_by_nonresidue() + a_a, c1: (self.c0 + self.c1) * (other.c0 + other.c1) - a_a - b_b + c_c.mul_by_nonresidue(), - c2: (self.c0 + self.c2) * (other.c0 + other.c2) - a_a + b_b - c_c + c2: (self.c0 + self.c2) * (other.c0 + other.c2) - a_a + b_b - c_c, } } } @@ -164,7 +214,7 @@ impl Sub for Fq6 { Fq6 { c0: self.c0 - other.c0, c1: self.c1 - other.c1, - c2: self.c2 - other.c2 + c2: self.c2 - other.c2, } } } @@ -176,7 +226,7 @@ impl Add for Fq6 { Fq6 { c0: self.c0 + other.c0, c1: self.c1 + other.c1, - c2: self.c2 + other.c2 + c2: self.c2 + other.c2, } } } @@ -188,7 +238,7 @@ impl Neg for Fq6 { Fq6 { c0: -self.c0, c1: -self.c1, - c2: -self.c2 + c2: -self.c2, } } } diff --git a/src/fields/mod.rs b/src/fields/mod.rs index 2c28284a..bd60b3e2 100644 --- a/src/fields/mod.rs +++ b/src/fields/mod.rs @@ -5,25 +5,25 @@ mod fq12; use arith::U256; use rand::Rng; -use std::ops::{Add, Sub, Mul, Neg}; +use std::ops::{Add, Mul, Neg, Sub}; use std::fmt::Debug; -pub use self::fp::{Fq, Fr, const_fq}; +pub use self::fp::{const_fq, Fq, Fr}; pub use self::fq2::{Fq2, fq2_nonresidue}; pub use self::fq6::Fq6; pub use self::fq12::Fq12; -pub trait FieldElement: Sized - + Copy - + Clone - + Add - + Sub - + Mul - + Neg - + PartialEq - + Eq - + Debug -{ +pub trait FieldElement + : Sized + + Copy + + Clone + + Add + + Sub + + Mul + + Neg + + PartialEq + + Eq + + Debug { fn zero() -> Self; fn one() -> Self; fn random(&mut R) -> Self; @@ -66,8 +66,18 @@ fn test_fq2() { #[test] fn test_str() { - assert_eq!(-Fr::one(), Fr::from_str("21888242871839275222246405745257275088548364400416034343698204186575808495616").unwrap()); - assert_eq!(-Fq::one(), Fq::from_str("21888242871839275222246405745257275088696311157297823662689037894645226208582").unwrap()); + assert_eq!( + -Fr::one(), + Fr::from_str( + "21888242871839275222246405745257275088548364400416034343698204186575808495616" + ).unwrap() + ); + assert_eq!( + -Fq::one(), + Fq::from_str( + "21888242871839275222246405745257275088696311157297823662689037894645226208582" + ).unwrap() + ); } #[test] @@ -85,32 +95,56 @@ fn fq12_test_vector() { let start = Fq12::new( Fq6::new( Fq2::new( - Fq::from_str("19797905000333868150253315089095386158892526856493194078073564469188852136946").unwrap(), - Fq::from_str("10509658143212501778222314067134547632307419253211327938344904628569123178733").unwrap() + Fq::from_str( + "19797905000333868150253315089095386158892526856493194078073564469188852136946", + ).unwrap(), + Fq::from_str( + "10509658143212501778222314067134547632307419253211327938344904628569123178733", + ).unwrap(), ), Fq2::new( - Fq::from_str("208316612133170645758860571704540129781090973693601051684061348604461399206").unwrap(), - Fq::from_str("12617661120538088237397060591907161689901553895660355849494983891299803248390").unwrap() + Fq::from_str( + "208316612133170645758860571704540129781090973693601051684061348604461399206", + ).unwrap(), + Fq::from_str( + "12617661120538088237397060591907161689901553895660355849494983891299803248390", + ).unwrap(), ), Fq2::new( - Fq::from_str("2897490589776053688661991433341220818937967872052418196321943489809183508515").unwrap(), - Fq::from_str("2730506433347642574983433139433778984782882168213690554721050571242082865799").unwrap() - ) + Fq::from_str( + "2897490589776053688661991433341220818937967872052418196321943489809183508515", + ).unwrap(), + Fq::from_str( + "2730506433347642574983433139433778984782882168213690554721050571242082865799", + ).unwrap(), + ), ), Fq6::new( Fq2::new( - Fq::from_str("17870056122431653936196746815433147921488990391314067765563891966783088591110").unwrap(), - Fq::from_str("14314041658607615069703576372547568077123863812415914883625850585470406221594").unwrap() + Fq::from_str( + "17870056122431653936196746815433147921488990391314067765563891966783088591110", + ).unwrap(), + Fq::from_str( + "14314041658607615069703576372547568077123863812415914883625850585470406221594", + ).unwrap(), ), Fq2::new( - Fq::from_str("10123533891707846623287020000407963680629966110211808794181173248765209982878").unwrap(), - Fq::from_str("5062091880848845693514855272640141851746424235009114332841857306926659567101").unwrap() + Fq::from_str( + "10123533891707846623287020000407963680629966110211808794181173248765209982878", + ).unwrap(), + Fq::from_str( + "5062091880848845693514855272640141851746424235009114332841857306926659567101", + ).unwrap(), ), Fq2::new( - Fq::from_str("9839781502639936537333620974973645053542086898304697594692219798017709586567").unwrap(), - Fq::from_str("1583892292110602864638265389721494775152090720173641072176370350017825640703").unwrap() - ) - ) + Fq::from_str( + "9839781502639936537333620974973645053542086898304697594692219798017709586567", + ).unwrap(), + Fq::from_str( + "1583892292110602864638265389721494775152090720173641072176370350017825640703", + ).unwrap(), + ), + ), ); // Do a bunch of arbitrary stuff to the element @@ -137,32 +171,56 @@ fn fq12_test_vector() { let finally = Fq12::new( Fq6::new( Fq2::new( - Fq::from_str("18388750939593263065521177085001223024106699964957029146547831509155008229833").unwrap(), - Fq::from_str("18370529854582635460997127698388761779167953912610241447912705473964014492243").unwrap() + Fq::from_str( + "18388750939593263065521177085001223024106699964957029146547831509155008229833", + ).unwrap(), + Fq::from_str( + "18370529854582635460997127698388761779167953912610241447912705473964014492243", + ).unwrap(), ), Fq2::new( - Fq::from_str("3691824277096717481466579496401243638295254271265821828017111951446539785268").unwrap(), - Fq::from_str("20513494218085713799072115076991457239411567892860153903443302793553884247235").unwrap() + Fq::from_str( + "3691824277096717481466579496401243638295254271265821828017111951446539785268", + ).unwrap(), + Fq::from_str( + "20513494218085713799072115076991457239411567892860153903443302793553884247235", + ).unwrap(), ), Fq2::new( - Fq::from_str("12214155472433286415803224222551966441740960297013786627326456052558698216399").unwrap(), - Fq::from_str("10987494248070743195602580056085773610850106455323751205990078881956262496575").unwrap() - ) + Fq::from_str( + "12214155472433286415803224222551966441740960297013786627326456052558698216399", + ).unwrap(), + Fq::from_str( + "10987494248070743195602580056085773610850106455323751205990078881956262496575", + ).unwrap(), + ), ), Fq6::new( Fq2::new( - Fq::from_str("5134522153456102954632718911439874984161223687865160221119284322136466794876").unwrap(), - Fq::from_str("20119236909927036376726859192821071338930785378711977469360149362002019539920").unwrap() + Fq::from_str( + "5134522153456102954632718911439874984161223687865160221119284322136466794876", + ).unwrap(), + Fq::from_str( + "20119236909927036376726859192821071338930785378711977469360149362002019539920", + ).unwrap(), ), Fq2::new( - Fq::from_str("8839766648621210419302228913265679710586991805716981851373026244791934012854").unwrap(), - Fq::from_str("9103032146464138788288547957401673544458789595252696070370942789051858719203").unwrap() + Fq::from_str( + "8839766648621210419302228913265679710586991805716981851373026244791934012854", + ).unwrap(), + Fq::from_str( + "9103032146464138788288547957401673544458789595252696070370942789051858719203", + ).unwrap(), ), Fq2::new( - Fq::from_str("10378379548636866240502412547812481928323945124508039853766409196375806029865").unwrap(), - Fq::from_str("9021627154807648093720460686924074684389554332435186899318369174351765754041").unwrap() - ) - ) + Fq::from_str( + "10378379548636866240502412547812481928323945124508039853766409196375806029865", + ).unwrap(), + Fq::from_str( + "9021627154807648093720460686924074684389554332435186899318369174351765754041", + ).unwrap(), + ), + ), ); assert_eq!(finally, next); @@ -172,27 +230,112 @@ fn fq12_test_vector() { fn test_cyclotomic_exp() { let orig = Fq12::new( Fq6::new( - Fq2::new(Fq::from_str("2259924035228092997691937637688451143058635253053054071159756458902878894295").unwrap(), Fq::from_str("13145690032701362144460254305183927872683620413225364127064863863535255135244").unwrap()), - Fq2::new(Fq::from_str("9910063591662383599552477067956819406417086889312288278252482503717089428441").unwrap(), Fq::from_str("537414042055419261990282459138081732565514913399498746664966841152381183961").unwrap()), - Fq2::new(Fq::from_str("15311812409497308894370893420777496684951030254049554818293571309705780605004").unwrap(), Fq::from_str("13657107176064455789881282546557276003626320193974643644160350907227082365810").unwrap()) + Fq2::new( + Fq::from_str( + "2259924035228092997691937637688451143058635253053054071159756458902878894295", + ).unwrap(), + Fq::from_str( + "13145690032701362144460254305183927872683620413225364127064863863535255135244", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "9910063591662383599552477067956819406417086889312288278252482503717089428441", + ).unwrap(), + Fq::from_str( + "537414042055419261990282459138081732565514913399498746664966841152381183961", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "15311812409497308894370893420777496684951030254049554818293571309705780605004", + ).unwrap(), + Fq::from_str( + "13657107176064455789881282546557276003626320193974643644160350907227082365810", + ).unwrap(), + ), + ), + Fq6::new( + Fq2::new( + Fq::from_str( + "4913017949003742946864670837361832856526234260447029873580022776602534856819", + ).unwrap(), + Fq::from_str( + "7834351480852267338070670220119081676575418514182895774094743209915633114041", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "12837298223308203788092748646758194441270207338661891973231184407371206766993", + ).unwrap(), + Fq::from_str( + "12756474445699147370503225379431475413909971718057034061593007812727141391799", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "9473802207170192255373153510655867502408045964296373712891954747252332944018", + ).unwrap(), + Fq::from_str( + "4583089109360519374075173304035813179013579459429335467869926761027310749713", + ).unwrap(), + ), ), - Fq6::new(Fq2::new(Fq::from_str("4913017949003742946864670837361832856526234260447029873580022776602534856819").unwrap(), Fq::from_str("7834351480852267338070670220119081676575418514182895774094743209915633114041").unwrap()), - Fq2::new(Fq::from_str("12837298223308203788092748646758194441270207338661891973231184407371206766993").unwrap(), Fq::from_str("12756474445699147370503225379431475413909971718057034061593007812727141391799").unwrap()), - Fq2::new(Fq::from_str("9473802207170192255373153510655867502408045964296373712891954747252332944018").unwrap(), Fq::from_str("4583089109360519374075173304035813179013579459429335467869926761027310749713").unwrap()) - ) ); let expected = Fq12::new( Fq6::new( - Fq2::new(Fq::from_str("14722956046055152398903846391223329501345567382234608299399030576415080188350").unwrap(), Fq::from_str("14280703280777926697010730619606819467080027543707671882210769811674790473417").unwrap()), - Fq2::new(Fq::from_str("19969875076083990244184003223190771301761436396530543002586073549972410735411").unwrap(), Fq::from_str("10717335566913889643303549252432531178405520196706173198634734518494041323243").unwrap()), - Fq2::new(Fq::from_str("6063612626166484870786832843320782567259894784043383626084549455432890717937").unwrap(), Fq::from_str("17089783040131779205038789608891431427943860868115199598200376195935079808729").unwrap()) + Fq2::new( + Fq::from_str( + "14722956046055152398903846391223329501345567382234608299399030576415080188350", + ).unwrap(), + Fq::from_str( + "14280703280777926697010730619606819467080027543707671882210769811674790473417", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "19969875076083990244184003223190771301761436396530543002586073549972410735411", + ).unwrap(), + Fq::from_str( + "10717335566913889643303549252432531178405520196706173198634734518494041323243", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "6063612626166484870786832843320782567259894784043383626084549455432890717937", + ).unwrap(), + Fq::from_str( + "17089783040131779205038789608891431427943860868115199598200376195935079808729", + ).unwrap(), + ), ), Fq6::new( - Fq2::new(Fq::from_str("10029863438921507421569931792104023129735006154272482043027653425575205672906").unwrap(), Fq::from_str("6406252222753462799887280578845937185621081001436094637606245493619821542775").unwrap()), - Fq2::new(Fq::from_str("1048245462913506652602966692378792381004227332967846949234978073448561848050").unwrap(), Fq::from_str("1444281375189053827455518242624554285012408033699861764136810522738182087554").unwrap()), - Fq2::new(Fq::from_str("8839610992666735109106629514135300820412539620261852250193684883379364789120").unwrap(), Fq::from_str("11347360242067273846784836674906058940820632082713814508736182487171407730718").unwrap()) - ) + Fq2::new( + Fq::from_str( + "10029863438921507421569931792104023129735006154272482043027653425575205672906", + ).unwrap(), + Fq::from_str( + "6406252222753462799887280578845937185621081001436094637606245493619821542775", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "1048245462913506652602966692378792381004227332967846949234978073448561848050", + ).unwrap(), + Fq::from_str( + "1444281375189053827455518242624554285012408033699861764136810522738182087554", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "8839610992666735109106629514135300820412539620261852250193684883379364789120", + ).unwrap(), + Fq::from_str( + "11347360242067273846784836674906058940820632082713814508736182487171407730718", + ).unwrap(), + ), + ), ); let e = orig.exp_by_neg_z(); diff --git a/src/fields/tests.rs b/src/fields/tests.rs index e9f738c1..1099f71d 100644 --- a/src/fields/tests.rs +++ b/src/fields/tests.rs @@ -1,4 +1,4 @@ -use rand::{Rng,SeedableRng,StdRng}; +use rand::{Rng, SeedableRng, StdRng}; use super::FieldElement; fn can_invert() { @@ -27,10 +27,7 @@ fn rand_element_eval(rng: &mut R) { let c = F::random(rng); let d = F::random(rng); - assert_eq!( - (a + b) * (c + d), - (a * c) + (b * c) + (a * d) + (b * d) - ); + assert_eq!((a + b) * (c + d), (a * c) + (b * c) + (a * d) + (b * d)); } } diff --git a/src/groups/mod.rs b/src/groups/mod.rs index 74b5eecc..b5c08a6f 100644 --- a/src/groups/mod.rs +++ b/src/groups/mod.rs @@ -1,23 +1,23 @@ -use std::ops::{Add,Sub,Neg,Mul}; -use fields::{FieldElement, Fq, Fq2, Fq12, Fr, const_fq, fq2_nonresidue}; +use std::ops::{Add, Mul, Neg, Sub}; +use fields::{const_fq, FieldElement, Fq, Fq12, Fq2, Fr, fq2_nonresidue}; use arith::U256; use std::fmt; use rand::Rng; #[cfg(feature = "rustc-serialize")] -use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; - -pub trait GroupElement: Sized + - Copy + - Clone + - PartialEq + - Eq + - fmt::Debug + - Add + - Sub + - Neg + - Mul -{ +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; + +pub trait GroupElement + : Sized + + Copy + + Clone + + PartialEq + + Eq + + fmt::Debug + + Add + + Sub + + Neg + + Mul { fn zero() -> Self; fn one() -> Self; fn random(rng: &mut R) -> Self; @@ -34,23 +34,21 @@ pub trait GroupParams: Sized { fn name() -> &'static str; fn one() -> G; fn coeff_b() -> Self::Base; - fn check_order() -> bool { false } + fn check_order() -> bool { + false + } } #[repr(C)] pub struct G { x: P::Base, y: P::Base, - z: P::Base + z: P::Base, } impl G

{ pub fn new(x: P::Base, y: P::Base, z: P::Base) -> Self { - G { - x: x, - y: y, - z: z, - } + G { x: x, y: y, z: z } } pub fn x(&self) -> &P::Base { @@ -67,7 +65,7 @@ impl G

{ pub fn y_mut(&mut self) -> &mut P::Base { &mut self.y - } + } pub fn z(&self) -> &P::Base { &self.z @@ -75,12 +73,12 @@ impl G

{ pub fn z_mut(&mut self) -> &mut P::Base { &mut self.z - } + } } pub struct AffineG { x: P::Base, - y: P::Base + y: P::Base, } #[derive(Debug)] @@ -96,18 +94,15 @@ impl AffineG

{ let p: G

= G { x: x, y: y, - z: P::Base::one() + z: P::Base::one(), }; if (p * (-Fr::one())) + p != G::zero() { - return Err(Error::NotInSubgroup) + return Err(Error::NotInSubgroup); } } - Ok(AffineG { - x: x, - y: y - }) + Ok(AffineG { x: x, y: y }) } else { Err(Error::NotOnCurve) } @@ -136,7 +131,7 @@ impl PartialEq for AffineG

{ } } -impl Eq for AffineG

{ } +impl Eq for AffineG

{} impl fmt::Debug for G

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -149,7 +144,7 @@ impl Clone for G

{ G { x: self.x, y: self.y, - z: self.z + z: self.z, } } } @@ -160,7 +155,7 @@ impl Clone for AffineG

{ fn clone(&self) -> Self { AffineG { x: self.x, - y: self.y + y: self.y, } } } @@ -170,7 +165,7 @@ impl Copy for AffineG

{} impl PartialEq for G

{ fn eq(&self, other: &Self) -> bool { if self.is_zero() { - return other.is_zero() + return other.is_zero(); } if other.is_zero() { @@ -194,7 +189,7 @@ impl PartialEq for G

{ return true; } } -impl Eq for G

{ } +impl Eq for G

{} impl G

{ pub fn to_affine(&self) -> Option> { @@ -203,7 +198,7 @@ impl G

{ } else if self.z == P::Base::one() { Some(AffineG { x: self.x, - y: self.y + y: self.y, }) } else { let zinv = self.z.inverse().unwrap(); @@ -211,7 +206,7 @@ impl G

{ Some(AffineG { x: self.x * zinv_squared, - y: self.y * (zinv_squared * zinv) + y: self.y * (zinv_squared * zinv), }) } } @@ -222,7 +217,7 @@ impl AffineG

{ G { x: self.x, y: self.y, - z: P::Base::one() + z: P::Base::one(), } } } @@ -271,11 +266,9 @@ impl Decodable for AffineG

{ let x = try!(P::Base::decode(s)); let y = try!(P::Base::decode(s)); - Self::new(x, y).map_err(|e| { - match e { - Error::NotOnCurve => s.error("point is not on the curve"), - Error::NotInSubgroup => s.error("point is not in the subgroup"), - } + Self::new(x, y).map_err(|e| match e { + Error::NotOnCurve => s.error("point is not on the curve"), + Error::NotInSubgroup => s.error("point is not in the subgroup"), }) } } @@ -285,7 +278,7 @@ impl GroupElement for G

{ G { x: P::Base::zero(), y: P::Base::one(), - z: P::Base::zero() + z: P::Base::zero(), } } @@ -318,7 +311,7 @@ impl GroupElement for G

{ G { x: x3, y: e * (d - x3) - eight_c, - z: y1z1 + y1z1 + z: y1z1 + y1z1, } } } @@ -381,7 +374,7 @@ impl Add> for G

{ G { x: x3, y: r * (v - x3) - (s1_j + s1_j), - z: ((self.z + other.z).squared() - z1_squared - z2_squared) * h + z: ((self.z + other.z).squared() - z1_squared - z2_squared) * h, } } } @@ -397,7 +390,7 @@ impl Neg for G

{ G { x: self.x, y: -self.y, - z: self.z + z: self.z, } } } @@ -409,7 +402,7 @@ impl Neg for AffineG

{ fn neg(self) -> AffineG

{ AffineG { x: self.x, - y: -self.y + y: -self.y, } } } @@ -427,18 +420,30 @@ pub struct G1Params; impl GroupParams for G1Params { type Base = Fq; - fn name() -> &'static str { "G1" } + fn name() -> &'static str { + "G1" + } fn one() -> G { G { x: Fq::one(), - y: const_fq([0xa6ba871b8b1e1b3a, 0x14f1d651eb8e167b, 0xccdd46def0f28c58, 0x1c14ef83340fbe5e]), - z: Fq::one() + y: const_fq([ + 0xa6ba871b8b1e1b3a, + 0x14f1d651eb8e167b, + 0xccdd46def0f28c58, + 0x1c14ef83340fbe5e, + ]), + z: Fq::one(), } } fn coeff_b() -> Fq { - const_fq([0x7a17caa950ad28d7, 0x1f6ac17ae15521b9, 0x334bea4e696bd284, 0x2a1f6744ce179d8e]) + const_fq([ + 0x7a17caa950ad28d7, + 0x1f6ac17ae15521b9, + 0x334bea4e696bd284, + 0x2a1f6744ce179d8e, + ]) } } @@ -451,30 +456,64 @@ pub struct G2Params; impl GroupParams for G2Params { type Base = Fq2; - fn name() -> &'static str { "G2" } + fn name() -> &'static str { + "G2" + } fn one() -> G { G { x: Fq2::new( - const_fq([0x8e83b5d102bc2026, 0xdceb1935497b0172, 0xfbb8264797811adf, 0x19573841af96503b]), - const_fq([0xafb4737da84c6140, 0x6043dd5a5802d8c4, 0x09e950fc52a02f86, 0x14fef0833aea7b6b]) + const_fq([ + 0x8e83b5d102bc2026, + 0xdceb1935497b0172, + 0xfbb8264797811adf, + 0x19573841af96503b, + ]), + const_fq([ + 0xafb4737da84c6140, + 0x6043dd5a5802d8c4, + 0x09e950fc52a02f86, + 0x14fef0833aea7b6b, + ]), ), y: Fq2::new( - const_fq([0x619dfa9d886be9f6, 0xfe7fd297f59e9b78, 0xff9e1a62231b7dfe, 0x28fd7eebae9e4206]), - const_fq([0x64095b56c71856ee, 0xdc57f922327d3cbb, 0x55f935be33351076, 0x0da4a0e693fd6482]) + const_fq([ + 0x619dfa9d886be9f6, + 0xfe7fd297f59e9b78, + 0xff9e1a62231b7dfe, + 0x28fd7eebae9e4206, + ]), + const_fq([ + 0x64095b56c71856ee, + 0xdc57f922327d3cbb, + 0x55f935be33351076, + 0x0da4a0e693fd6482, + ]), ), - z: Fq2::one() + z: Fq2::one(), } } fn coeff_b() -> Fq2 { Fq2::new( - const_fq([0x3bf938e377b802a8, 0x020b1b273633535d, 0x26b7edf049755260, 0x2514c6324384a86d]), - const_fq([0x38e7ecccd1dcff67, 0x65f0b37d93ce0d3e, 0xd749d0dd22ac00aa, 0x0141b9ce4a688d4d]) + const_fq([ + 0x3bf938e377b802a8, + 0x020b1b273633535d, + 0x26b7edf049755260, + 0x2514c6324384a86d, + ]), + const_fq([ + 0x38e7ecccd1dcff67, + 0x65f0b37d93ce0d3e, + 0xd749d0dd22ac00aa, + 0x0141b9ce4a688d4d, + ]), ) } - fn check_order() -> bool { true } + fn check_order() -> bool { + true + } } pub type G2 = G; @@ -525,27 +564,57 @@ fn twist() -> Fq2 { #[inline] fn two_inv() -> Fq { - const_fq([9781510331150239090, 15059239858463337189, 10331104244869713732, 2249375503248834476]) + const_fq([ + 9781510331150239090, + 15059239858463337189, + 10331104244869713732, + 2249375503248834476, + ]) } #[inline] fn ate_loop_count() -> U256 { - U256([0x9d797039be763ba8, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000]) + U256([ + 0x9d797039be763ba8, + 0x0000000000000001, + 0x0000000000000000, + 0x0000000000000000, + ]) } #[inline] fn twist_mul_by_q_x() -> Fq2 { Fq2::new( - const_fq([13075984984163199792, 3782902503040509012, 8791150885551868305, 1825854335138010348]), - const_fq([7963664994991228759, 12257807996192067905, 13179524609921305146, 2767831111890561987]) + const_fq([ + 13075984984163199792, + 3782902503040509012, + 8791150885551868305, + 1825854335138010348, + ]), + const_fq([ + 7963664994991228759, + 12257807996192067905, + 13179524609921305146, + 2767831111890561987, + ]), ) } #[inline] fn twist_mul_by_q_y() -> Fq2 { Fq2::new( - const_fq([16482010305593259561, 13488546290961988299, 3578621962720924518, 2681173117283399901]), - const_fq([11661927080404088775, 553939530661941723, 7860678177968807019, 3208568454732775116]) + const_fq([ + 16482010305593259561, + 13488546290961988299, + 3578621962720924518, + 2681173117283399901, + ]), + const_fq([ + 11661927080404088775, + 553939530661941723, + 7860678177968807019, + 3208568454732775116, + ]), ) } @@ -553,13 +622,13 @@ fn twist_mul_by_q_y() -> Fq2 { pub struct EllCoeffs { pub ell_0: Fq2, pub ell_vw: Fq2, - pub ell_vv: Fq2 + pub ell_vv: Fq2, } #[derive(PartialEq, Eq)] pub struct G2Precomp { pub q: AffineG, - pub coeffs: Vec + pub coeffs: Vec, } impl G2Precomp { @@ -579,7 +648,8 @@ impl G2Precomp { let c = &self.coeffs[idx]; idx += 1; - f = f.squared().mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x)); + f = f.squared() + .mul_by_024(c.ell_0, c.ell_vw.scale(g1.y), c.ell_vv.scale(g1.x)); if i { let c = &self.coeffs[idx]; @@ -603,8 +673,14 @@ impl G2Precomp { fn test_miller_loop() { use fields::Fq6; - let g1 = G1::one() * Fr::from_str("18097487326282793650237947474982649264364522469319914492172746413872781676").unwrap(); - let g2 = G2::one() * Fr::from_str("20390255904278144451778773028944684152769293537511418234311120800877067946").unwrap(); + let g1 = G1::one() + * Fr::from_str( + "18097487326282793650237947474982649264364522469319914492172746413872781676", + ).unwrap(); + let g2 = G2::one() + * Fr::from_str( + "20390255904278144451778773028944684152769293537511418234311120800877067946", + ).unwrap(); let g1_pre = g1.to_affine().unwrap(); let g2_pre = g2.to_affine().unwrap().precompute(); @@ -630,7 +706,7 @@ impl AffineG { fn mul_by_q(&self) -> Self { AffineG { x: twist_mul_by_q_x() * self.x.frobenius_map(1), - y: twist_mul_by_q_y() * self.y.frobenius_map(1) + y: twist_mul_by_q_y() * self.y.frobenius_map(1), } } @@ -663,13 +739,16 @@ impl AffineG { G2Precomp { q: *self, - coeffs: coeffs + coeffs: coeffs, } } } impl G2 { - fn mixed_addition_step_for_flipped_miller_loop(&mut self, base: &AffineG) -> EllCoeffs { + fn mixed_addition_step_for_flipped_miller_loop( + &mut self, + base: &AffineG, + ) -> EllCoeffs { let d = self.x - self.z * base.x; let e = self.y - self.z * base.y; let f = d.squared(); @@ -685,7 +764,7 @@ impl G2 { EllCoeffs { ell_0: twist() * (e * base.x - d * base.y), ell_vv: e.neg(), - ell_vw: d + ell_vw: d, } } @@ -709,14 +788,17 @@ impl G2 { EllCoeffs { ell_0: twist() * i, ell_vw: h.neg(), - ell_vv: j + j + j + ell_vv: j + j + j, } } } #[test] fn test_prepared_g2() { - let g2 = G2::one() * Fr::from_str("20390255904278144451778773028944684152769293537511418234311120800877067946").unwrap(); + let g2 = G2::one() + * Fr::from_str( + "20390255904278144451778773028944684152769293537511418234311120800877067946", + ).unwrap(); let g2_p = g2.to_affine().unwrap().precompute(); @@ -844,9 +926,10 @@ fn test_prepared_g2() { pub fn pairing(p: &G1, q: &G2) -> Fq12 { match (p.to_affine(), q.to_affine()) { (None, _) | (_, None) => Fq12::one(), - (Some(p), Some(q)) => { - q.precompute().miller_loop(&p).final_exponentiation().expect("miller loop cannot produce zero") - } + (Some(p), Some(q)) => q.precompute() + .miller_loop(&p) + .final_exponentiation() + .expect("miller loop cannot produce zero"), } } @@ -854,22 +937,70 @@ pub fn pairing(p: &G1, q: &G2) -> Fq12 { fn test_reduced_pairing() { use fields::Fq6; - let g1 = G1::one() * Fr::from_str("18097487326282793650237947474982649264364522469319914492172746413872781676").unwrap(); - let g2 = G2::one() * Fr::from_str("20390255904278144451778773028944684152769293537511418234311120800877067946").unwrap(); + let g1 = G1::one() + * Fr::from_str( + "18097487326282793650237947474982649264364522469319914492172746413872781676", + ).unwrap(); + let g2 = G2::one() + * Fr::from_str( + "20390255904278144451778773028944684152769293537511418234311120800877067946", + ).unwrap(); let gt = pairing(&g1, &g2); let expected = Fq12::new( Fq6::new( - Fq2::new(Fq::from_str("7520311483001723614143802378045727372643587653754534704390832890681688842501").unwrap(), Fq::from_str("20265650864814324826731498061022229653175757397078253377158157137251452249882").unwrap()), - Fq2::new(Fq::from_str("11942254371042183455193243679791334797733902728447312943687767053513298221130").unwrap(), Fq::from_str("759657045325139626991751731924144629256296901790485373000297868065176843620").unwrap()), - Fq2::new(Fq::from_str("16045761475400271697821392803010234478356356448940805056528536884493606035236").unwrap(), Fq::from_str("4715626119252431692316067698189337228571577552724976915822652894333558784086").unwrap()) + Fq2::new( + Fq::from_str( + "7520311483001723614143802378045727372643587653754534704390832890681688842501", + ).unwrap(), + Fq::from_str( + "20265650864814324826731498061022229653175757397078253377158157137251452249882", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "11942254371042183455193243679791334797733902728447312943687767053513298221130", + ).unwrap(), + Fq::from_str( + "759657045325139626991751731924144629256296901790485373000297868065176843620", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "16045761475400271697821392803010234478356356448940805056528536884493606035236", + ).unwrap(), + Fq::from_str( + "4715626119252431692316067698189337228571577552724976915822652894333558784086", + ).unwrap(), + ), ), Fq6::new( - Fq2::new(Fq::from_str("14901948363362882981706797068611719724999331551064314004234728272909570402962").unwrap(), Fq::from_str("11093203747077241090565767003969726435272313921345853819385060670210834379103").unwrap()), - Fq2::new(Fq::from_str("17897835398184801202802503586172351707502775171934235751219763553166796820753").unwrap(), Fq::from_str("1344517825169318161285758374052722008806261739116142912817807653057880346554").unwrap()), - Fq2::new(Fq::from_str("11123896897251094532909582772961906225000817992624500900708432321664085800838").unwrap(), Fq::from_str("17453370448280081813275586256976217762629631160552329276585874071364454854650").unwrap()) - ) + Fq2::new( + Fq::from_str( + "14901948363362882981706797068611719724999331551064314004234728272909570402962", + ).unwrap(), + Fq::from_str( + "11093203747077241090565767003969726435272313921345853819385060670210834379103", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "17897835398184801202802503586172351707502775171934235751219763553166796820753", + ).unwrap(), + Fq::from_str( + "1344517825169318161285758374052722008806261739116142912817807653057880346554", + ).unwrap(), + ), + Fq2::new( + Fq::from_str( + "11123896897251094532909582772961906225000817992624500900708432321664085800838", + ).unwrap(), + Fq::from_str( + "17453370448280081813275586256976217762629631160552329276585874071364454854650", + ).unwrap(), + ), + ), ); assert_eq!(expected, gt); @@ -878,9 +1009,10 @@ fn test_reduced_pairing() { #[test] fn predefined_pair() { let g1 = AffineG1::new( - Fq::from_str("1").expect("Fq(1) should exist"), + Fq::from_str("1").expect("Fq(1) should exist"), Fq::from_str("2").expect("Fq(2) should exist"), - ).expect("Point (1,2) should exist in G1").to_jacobian(); + ).expect("Point (1,2) should exist in G1") + .to_jacobian(); let g2 = AffineG2::new( Fq2::new( @@ -905,7 +1037,7 @@ fn predefined_pair() { #[test] fn test_binlinearity() { - use rand::{SeedableRng,StdRng}; + use rand::{SeedableRng, StdRng}; let seed: [usize; 4] = [103245, 191922, 1293, 192103]; let mut rng = StdRng::from_seed(&seed); @@ -934,13 +1066,10 @@ fn test_binlinearity() { fn internals() { let test_p = G1::one(); - let val = G1::new( - test_p.x().clone(), - test_p.y().clone(), - test_p.z().clone(), - ); + let val = G1::new(test_p.x().clone(), test_p.y().clone(), test_p.z().clone()); - let affine = val.to_affine().expect("There should be affine coords for (0, 0)"); + let affine = val.to_affine() + .expect("There should be affine coords for (0, 0)"); assert_eq!(affine.x(), &Fq::one()); } @@ -948,13 +1077,19 @@ fn internals() { #[test] fn affine_fail() { let res = AffineG1::new(Fq::one(), Fq::one()); - assert!(res.is_err(), "Affine initialization should fail because the point is not on curve"); + assert!( + res.is_err(), + "Affine initialization should fail because the point is not on curve" + ); } #[test] fn affine_ok() { let res = AffineG1::new(Fq::one(), G1Params::coeff_b()); - assert!(res.is_err(), "Affine initialization should be ok because the point is on the curve"); + assert!( + res.is_err(), + "Affine initialization should be ok because the point is on the curve" + ); } #[test] diff --git a/src/groups/tests.rs b/src/groups/tests.rs index 3b32fb87..71ce5589 100644 --- a/src/groups/tests.rs +++ b/src/groups/tests.rs @@ -90,7 +90,7 @@ pub fn group_trials() { assert!((G::one() * (-Fr::one()) + G::one()).is_zero()); - use rand::{SeedableRng,StdRng}; + use rand::{SeedableRng, StdRng}; let seed: [usize; 4] = [103245, 191922, 1293, 192103]; let mut rng = StdRng::from_seed(&seed); @@ -99,4 +99,3 @@ pub fn group_trials() { random_test_dh::(&mut rng); random_test_equality::(&mut rng); } - diff --git a/src/lib.rs b/src/lib.rs index d583e02d..6c8b5687 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ +extern crate byteorder; +#[macro_use] +extern crate crunchy; extern crate rand; #[cfg(feature = "rustc-serialize")] extern crate rustc_serialize; -extern crate byteorder; pub mod arith; mod fields; @@ -10,7 +12,7 @@ mod groups; use fields::FieldElement; use groups::GroupElement; -use std::ops::{Add, Sub, Mul, Neg}; +use std::ops::{Add, Mul, Neg, Sub}; use rand::Rng; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -19,13 +21,27 @@ use rand::Rng; pub struct Fr(fields::Fr); impl Fr { - pub fn zero() -> Self { Fr(fields::Fr::zero()) } - pub fn one() -> Self { Fr(fields::Fr::one()) } - pub fn random(rng: &mut R) -> Self { Fr(fields::Fr::random(rng)) } - pub fn pow(&self, exp: Fr) -> Self { Fr(self.0.pow(exp.0)) } - pub fn from_str(s: &str) -> Option { fields::Fr::from_str(s).map(|e| Fr(e)) } - pub fn inverse(&self) -> Option { self.0.inverse().map(|e| Fr(e)) } - pub fn is_zero(&self) -> bool { self.0.is_zero() } + pub fn zero() -> Self { + Fr(fields::Fr::zero()) + } + pub fn one() -> Self { + Fr(fields::Fr::one()) + } + pub fn random(rng: &mut R) -> Self { + Fr(fields::Fr::random(rng)) + } + pub fn pow(&self, exp: Fr) -> Self { + Fr(self.0.pow(exp.0)) + } + pub fn from_str(s: &str) -> Option { + fields::Fr::from_str(s).map(|e| Fr(e)) + } + pub fn inverse(&self) -> Option { + self.0.inverse().map(|e| Fr(e)) + } + pub fn is_zero(&self) -> bool { + self.0.is_zero() + } pub fn interpret(buf: &[u8; 64]) -> Fr { Fr(fields::Fr::interpret(buf)) } @@ -36,32 +52,43 @@ impl Fr { .map(|x| Fr(x)) } pub fn to_big_endian(&self, slice: &mut [u8]) -> Result<(), FieldError> { - self.0.raw().to_big_endian(slice).map_err(|_| FieldError::InvalidSliceLength) + self.0 + .raw() + .to_big_endian(slice) + .map_err(|_| FieldError::InvalidSliceLength) } } impl Add for Fr { type Output = Fr; - fn add(self, other: Fr) -> Fr { Fr(self.0 + other.0) } + fn add(self, other: Fr) -> Fr { + Fr(self.0 + other.0) + } } impl Sub for Fr { type Output = Fr; - fn sub(self, other: Fr) -> Fr { Fr(self.0 - other.0) } + fn sub(self, other: Fr) -> Fr { + Fr(self.0 - other.0) + } } impl Neg for Fr { type Output = Fr; - fn neg(self) -> Fr { Fr(-self.0) } + fn neg(self) -> Fr { + Fr(-self.0) + } } impl Mul for Fr { type Output = Fr; - fn mul(self, other: Fr) -> Fr { Fr(self.0 * other.0) } + fn mul(self, other: Fr) -> Fr { + Fr(self.0 * other.0) + } } #[derive(Debug)] @@ -78,13 +105,27 @@ pub use groups::Error as GroupError; pub struct Fq(fields::Fq); impl Fq { - pub fn zero() -> Self { Fq(fields::Fq::zero()) } - pub fn one() -> Self { Fq(fields::Fq::one()) } - pub fn random(rng: &mut R) -> Self { Fq(fields::Fq::random(rng)) } - pub fn pow(&self, exp: Fq) -> Self { Fq(self.0.pow(exp.0)) } - pub fn from_str(s: &str) -> Option { fields::Fq::from_str(s).map(|e| Fq(e)) } - pub fn inverse(&self) -> Option { self.0.inverse().map(|e| Fq(e)) } - pub fn is_zero(&self) -> bool { self.0.is_zero() } + pub fn zero() -> Self { + Fq(fields::Fq::zero()) + } + pub fn one() -> Self { + Fq(fields::Fq::one()) + } + pub fn random(rng: &mut R) -> Self { + Fq(fields::Fq::random(rng)) + } + pub fn pow(&self, exp: Fq) -> Self { + Fq(self.0.pow(exp.0)) + } + pub fn from_str(s: &str) -> Option { + fields::Fq::from_str(s).map(|e| Fq(e)) + } + pub fn inverse(&self) -> Option { + self.0.inverse().map(|e| Fq(e)) + } + pub fn is_zero(&self) -> bool { + self.0.is_zero() + } pub fn interpret(buf: &[u8; 64]) -> Fq { Fq(fields::Fq::interpret(buf)) } @@ -97,33 +138,46 @@ impl Fq { pub fn to_big_endian(&self, slice: &mut [u8]) -> Result<(), FieldError> { let mut a: arith::U256 = self.0.into(); // convert from Montgomery representation - a.mul(&fields::Fq::one().raw(), &fields::Fq::modulus(), self.0.inv()); - a.to_big_endian(slice).map_err(|_| FieldError::InvalidSliceLength) + a.mul( + &fields::Fq::one().raw(), + &fields::Fq::modulus(), + self.0.inv(), + ); + a.to_big_endian(slice) + .map_err(|_| FieldError::InvalidSliceLength) } } impl Add for Fq { type Output = Fq; - fn add(self, other: Fq) -> Fq { Fq(self.0 + other.0) } + fn add(self, other: Fq) -> Fq { + Fq(self.0 + other.0) + } } impl Sub for Fq { type Output = Fq; - fn sub(self, other: Fq) -> Fq { Fq(self.0 - other.0) } + fn sub(self, other: Fq) -> Fq { + Fq(self.0 - other.0) + } } impl Neg for Fq { type Output = Fq; - fn neg(self) -> Fq { Fq(-self.0) } + fn neg(self) -> Fq { + Fq(-self.0) + } } impl Mul for Fq { type Output = Fq; - fn mul(self, other: Fq) -> Fq { Fq(self.0 * other.0) } + fn mul(self, other: Fq) -> Fq { + Fq(self.0 * other.0) + } } pub struct Fq2(fields::Fq2); @@ -135,7 +189,7 @@ impl Fq2 { pub fn zero() -> Fq2 { Fq2(fields::Fq2::zero()) - } + } /// Initalizes new F_q2(a + bi, a is real coeff, b is imaginary) pub fn new(a: Fq, b: Fq) -> Fq2 { @@ -148,21 +202,20 @@ impl Fq2 { } #[cfg(feature = "rustc-serialize")] -pub trait Group: - rustc_serialize::Encodable + - rustc_serialize::Decodable + - Send + - Sync + - Copy + - Clone + - PartialEq + - Eq + - Sized + - Add + - Sub + - Neg + - Mul -{ +pub trait Group + : rustc_serialize::Encodable + + rustc_serialize::Decodable + + Send + + Sync + + Copy + + Clone + + PartialEq + + Eq + + Sized + + Add + + Sub + + Neg + + Mul { fn zero() -> Self; fn one() -> Self; fn random(rng: &mut R) -> Self; @@ -171,19 +224,18 @@ pub trait Group: } #[cfg(not(feature = "rustc-serialize"))] -pub trait Group: - Send + - Sync + - Copy + - Clone + - PartialEq + - Eq + - Sized + - Add + - Sub + - Neg + - Mul -{ +pub trait Group + : Send + + Sync + + Copy + + Clone + + PartialEq + + Eq + + Sized + + Add + + Sub + + Neg + + Mul { fn zero() -> Self; fn one() -> Self; fn random(rng: &mut R) -> Self; @@ -215,7 +267,7 @@ impl G1 { pub fn set_y(&mut self, y: Fq) { *self.0.y_mut() = y.0 - } + } pub fn z(&self) -> Fq { Fq(self.0.z().clone()) @@ -223,18 +275,26 @@ impl G1 { pub fn set_z(&mut self, z: Fq) { *self.0.z_mut() = z.0 - } + } } impl Group for G1 { - fn zero() -> Self { G1(groups::G1::zero()) } - fn one() -> Self { G1(groups::G1::one()) } - fn random(rng: &mut R) -> Self { G1(groups::G1::random(rng)) } - fn is_zero(&self) -> bool { self.0.is_zero() } + fn zero() -> Self { + G1(groups::G1::zero()) + } + fn one() -> Self { + G1(groups::G1::one()) + } + fn random(rng: &mut R) -> Self { + G1(groups::G1::random(rng)) + } + fn is_zero(&self) -> bool { + self.0.is_zero() + } fn normalize(&mut self) { let new = match self.0.to_affine() { Some(a) => a, - None => return + None => return, }; self.0 = new.to_jacobian(); @@ -244,25 +304,33 @@ impl Group for G1 { impl Add for G1 { type Output = G1; - fn add(self, other: G1) -> G1 { G1(self.0 + other.0) } + fn add(self, other: G1) -> G1 { + G1(self.0 + other.0) + } } impl Sub for G1 { type Output = G1; - fn sub(self, other: G1) -> G1 { G1(self.0 - other.0) } + fn sub(self, other: G1) -> G1 { + G1(self.0 - other.0) + } } impl Neg for G1 { type Output = G1; - fn neg(self) -> G1 { G1(-self.0) } + fn neg(self) -> G1 { + G1(-self.0) + } } impl Mul for G1 { type Output = G1; - fn mul(self, other: Fr) -> G1 { G1(self.0 * other.0) } + fn mul(self, other: Fr) -> G1 { + G1(self.0 * other.0) + } } #[derive(Copy, Clone, PartialEq, Eq)] @@ -289,7 +357,7 @@ impl AffineG1 { pub fn set_y(&mut self, y: Fq) { *self.0.y_mut() = y.0 - } + } pub fn from_jacobian(g1: G1) -> Option { g1.0.to_affine().map(|x| AffineG1(x)) @@ -326,7 +394,7 @@ impl G2 { pub fn set_y(&mut self, y: Fq2) { *self.0.y_mut() = y.0 - } + } pub fn z(&self) -> Fq2 { Fq2(self.0.z().clone()) @@ -334,18 +402,26 @@ impl G2 { pub fn set_z(&mut self, z: Fq2) { *self.0.z_mut() = z.0 - } + } } impl Group for G2 { - fn zero() -> Self { G2(groups::G2::zero()) } - fn one() -> Self { G2(groups::G2::one()) } - fn random(rng: &mut R) -> Self { G2(groups::G2::random(rng)) } - fn is_zero(&self) -> bool { self.0.is_zero() } + fn zero() -> Self { + G2(groups::G2::zero()) + } + fn one() -> Self { + G2(groups::G2::one()) + } + fn random(rng: &mut R) -> Self { + G2(groups::G2::random(rng)) + } + fn is_zero(&self) -> bool { + self.0.is_zero() + } fn normalize(&mut self) { let new = match self.0.to_affine() { Some(a) => a, - None => return + None => return, }; self.0 = new.to_jacobian(); @@ -355,25 +431,33 @@ impl Group for G2 { impl Add for G2 { type Output = G2; - fn add(self, other: G2) -> G2 { G2(self.0 + other.0) } + fn add(self, other: G2) -> G2 { + G2(self.0 + other.0) + } } impl Sub for G2 { type Output = G2; - fn sub(self, other: G2) -> G2 { G2(self.0 - other.0) } + fn sub(self, other: G2) -> G2 { + G2(self.0 - other.0) + } } impl Neg for G2 { type Output = G2; - fn neg(self) -> G2 { G2(-self.0) } + fn neg(self) -> G2 { + G2(-self.0) + } } impl Mul for G2 { type Output = G2; - fn mul(self, other: Fr) -> G2 { G2(self.0 * other.0) } + fn mul(self, other: Fr) -> G2 { + G2(self.0 * other.0) + } } #[derive(Copy, Clone, PartialEq, Eq)] @@ -381,15 +465,23 @@ impl Mul for G2 { pub struct Gt(fields::Fq12); impl Gt { - pub fn one() -> Self { Gt(fields::Fq12::one()) } - pub fn pow(&self, exp: Fr) -> Self { Gt(self.0.pow(exp.0)) } - pub fn inverse(&self) -> Self { Gt(self.0.inverse().unwrap()) } + pub fn one() -> Self { + Gt(fields::Fq12::one()) + } + pub fn pow(&self, exp: Fr) -> Self { + Gt(self.0.pow(exp.0)) + } + pub fn inverse(&self) -> Self { + Gt(self.0.inverse().unwrap()) + } } impl Mul for Gt { type Output = Gt; - fn mul(self, other: Gt) -> Gt { Gt(self.0 * other.0) } + fn mul(self, other: Gt) -> Gt { + Gt(self.0 * other.0) + } } pub fn pairing(p: G1, q: G2) -> Gt { @@ -420,7 +512,7 @@ impl AffineG2 { pub fn set_y(&mut self, y: Fq2) { *self.0.y_mut() = y.0 - } + } pub fn from_jacobian(g2: G2) -> Option { g2.0.to_affine().map(|x| AffineG2(x))