From cfa5857199b5631463404749df5816400cd7552b Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Sat, 21 Mar 2020 07:36:44 -0600 Subject: [PATCH 01/15] Fixed warnings Signed-off-by: Michael Lodder --- Cargo.toml | 4 +- src/constants.rs | 28 +++++----- src/extension_field_gt.rs | 32 +++++------ src/field_elem.rs | 113 +++++++++++++++++++------------------- src/group_elem.rs | 24 ++++---- src/group_elem_g1.rs | 28 +++++----- src/group_elem_g2.rs | 34 ++++++------ src/types_g2.rs | 6 +- src/utils.rs | 55 +++++++++---------- 9 files changed, 161 insertions(+), 163 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e4f9efb..e1ca2c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "amcl_wrapper" -version = "0.3.5" -authors = ["lovesh harchandani "] +version = "0.4.0" +authors = ["lovesh harchandani ", "Michael Lodder "] description = "Wapper over Milagro Cryptographic Library (version 3)" repository = "https://github.com/lovesh/amcl_rust_wrapper" diff --git a/src/constants.rs b/src/constants.rs index 76755f7..e9f4933 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -5,22 +5,22 @@ use super::ECCurve::rom; pub const MODBYTES: usize = curve_MODBYTES; pub const NLEN: usize = curve_NLEN; -pub const BigNumBits: usize = BASEBITS; +pub const BIG_NUM_BITS: usize = BASEBITS; // Byte size of element in group G1, 1 extra byte for compression flag -pub const FieldElement_SIZE: usize = MODBYTES; +pub const FIELD_ELEMENT_SIZE: usize = MODBYTES; // Byte size of element in group G1, 1 extra byte for compression flag -pub const GroupG1_SIZE: usize = (2 * MODBYTES + 1) as usize; +pub const GROUP_G1_SIZE: usize = (2 * MODBYTES + 1) as usize; lazy_static! { - pub static ref GeneratorG1: GroupG1 = GroupG1::generator(); - pub static ref CurveOrder: BigNum = BigNum::new_ints(&rom::CURVE_ORDER); - pub static ref CurveOrderBitSize: usize = CurveOrder.nbits(); - pub static ref FieldElementZero: BigNum = BigNum::new(); - pub static ref BarrettRedc_k: usize = CurveOrder.nbits(); - pub static ref BarrettRedc_u: BigNum = { - let k = CurveOrder.nbits(); + pub static ref GENERATOR_G1: GroupG1 = GroupG1::generator(); + pub static ref CURVE_ORDER: BigNum = BigNum::new_ints(&rom::CURVE_ORDER); + pub static ref CURVE_ORDER_BIT_SIZE: usize = CURVE_ORDER.nbits(); + pub static ref FIELD_ELEMENT_ZERO: BigNum = BigNum::new(); + pub static ref BARRETT_REDC_K: usize = CURVE_ORDER.nbits(); + pub static ref BARRETT_REDC_U: BigNum = { + let k = CURVE_ORDER.nbits(); let mut u = DoubleBigNum::new(); u.w[0] = 1; // `u.shl(2*k)` crashes, so perform shl(k) twice @@ -28,11 +28,11 @@ lazy_static! { u.shl(k); // div returns floored value - u.div(&CurveOrder) + u.div(&CURVE_ORDER) }; - pub static ref BarrettRedc_v: BigNum = { - let k = CurveOrder.nbits(); + pub static ref BARRETT_REDC_V: BigNum = { + let k = CURVE_ORDER.nbits(); let mut v = BigNum::new_int(1isize); v.shl(k+1); v @@ -40,4 +40,4 @@ lazy_static! { } #[cfg(any(feature = "bls381", feature = "bn254"))] -pub use crate::types_g2::{GeneratorG2, GroupG2_SIZE, GroupGT_SIZE}; +pub use crate::types_g2::{GENERATOR_G2, GROUP_G2_SIZE, GROUP_GT_SIZE}; diff --git a/src/extension_field_gt.rs b/src/extension_field_gt.rs index c83a6d0..04e3510 100644 --- a/src/extension_field_gt.rs +++ b/src/extension_field_gt.rs @@ -3,19 +3,19 @@ use crate::types::GroupGT; use super::ECCurve::fp12::{DENSE, FP12}; use super::ECCurve::fp4::FP4; use super::ECCurve::pair::{another, ate, ate2, fexp, initmp, miller}; -use crate::constants::GroupGT_SIZE; +use crate::constants::GROUP_GT_SIZE; use crate::errors::{SerzDeserzError, ValueError}; use crate::field_elem::FieldElement; use crate::group_elem::GroupElement; use crate::group_elem_g1::G1; -use crate::group_elem_g2::{parse_hex_as_FP2, G2}; +use crate::group_elem_g2::{parse_hex_as_fp2, G2}; use std::fmt; use std::hash::{Hash, Hasher}; use std::ops::Mul; use serde::de::{Deserialize, Deserializer, Error as DError, Visitor}; -use serde::ser::{Error as SError, Serialize, Serializer}; -use std::str::{FromStr, SplitWhitespace}; +use serde::ser::{Serialize, Serializer}; +use std::str::SplitWhitespace; use zeroize::Zeroize; #[derive(Clone)] @@ -132,16 +132,16 @@ impl GT { pub fn to_bytes(&self) -> Vec { let mut temp = FP12::new(); temp.copy(&self.value); - let mut bytes: [u8; GroupGT_SIZE] = [0; GroupGT_SIZE]; + let mut bytes: [u8; GROUP_GT_SIZE] = [0; GROUP_GT_SIZE]; temp.tobytes(&mut bytes); bytes.to_vec() } pub fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != GroupGT_SIZE { + if bytes.len() != GROUP_GT_SIZE { return Err(SerzDeserzError::GTBytesIncorrectSize( bytes.len(), - GroupGT_SIZE, + GROUP_GT_SIZE, )); } Ok(Self { @@ -152,10 +152,10 @@ impl GT { /// Writes bytes to given slice. Raises exception when given slice is not of /// desired length. pub fn write_to_slice(&self, target: &mut [u8]) -> Result<(), SerzDeserzError> { - if target.len() != GroupGT_SIZE { + if target.len() != GROUP_GT_SIZE { return Err(SerzDeserzError::GTBytesIncorrectSize( target.len(), - GroupGT_SIZE, + GROUP_GT_SIZE, )); } let mut temp = FP12::new(); @@ -178,9 +178,9 @@ impl GT { pub fn from_hex(s: String) -> Result { let mut iter = s.split_whitespace(); - let a = parse_hex_as_FP4(&mut iter)?; - let b = parse_hex_as_FP4(&mut iter)?; - let c = parse_hex_as_FP4(&mut iter)?; + let a = parse_hex_as_fp4(&mut iter)?; + let b = parse_hex_as_fp4(&mut iter)?; + let c = parse_hex_as_fp4(&mut iter)?; let mut value = FP12::new(); value.seta(a); value.setb(b); @@ -199,13 +199,13 @@ impl GT { } /// Parse given hex string as FP4 -pub fn parse_hex_as_FP4(iter: &mut SplitWhitespace) -> Result { +pub fn parse_hex_as_fp4(iter: &mut SplitWhitespace) -> Result { // Logic almost copied from AMCL but with error handling and constant time execution. // Constant time is important as hex is used during serialization and deserialization. // A seemingly effortless solution is to filter string for errors and pad with 0s before // passing to AMCL but that would be expensive as the string is scanned twice - let a = parse_hex_as_FP2(iter)?; - let b = parse_hex_as_FP2(iter)?; + let a = parse_hex_as_fp2(iter)?; + let b = parse_hex_as_fp2(iter)?; let mut fp4 = FP4::new(); fp4.seta(a); fp4.setb(b); @@ -218,7 +218,7 @@ impl PartialEq for GT { } } -impl_group_elem_conversions!(GT, GroupGT, GroupGT_SIZE); +impl_group_elem_conversions!(GT, GroupGT, GROUP_GT_SIZE); impl_group_elem_traits!(GT, GroupGT); diff --git a/src/field_elem.rs b/src/field_elem.rs index bcaceb9..4bcc78a 100644 --- a/src/field_elem.rs +++ b/src/field_elem.rs @@ -1,12 +1,11 @@ use rand::{CryptoRng, RngCore}; use crate::constants::{ - BarrettRedc_k, BarrettRedc_u, BarrettRedc_v, BigNumBits, CurveOrder, FieldElement_SIZE, NLEN, + BARRETT_REDC_K, BARRETT_REDC_U, BARRETT_REDC_V, BIG_NUM_BITS, CURVE_ORDER, FIELD_ELEMENT_SIZE, NLEN, }; use crate::errors::{SerzDeserzError, ValueError}; use crate::types::{BigNum, DoubleBigNum, Limb}; -use crate::utils::{barrett_reduction, get_seeded_RNG, get_seeded_RNG_with_rng, hash_msg}; -use amcl::arch::CHUNK; +use crate::utils::{barrett_reduction, get_seeded_rng, get_seeded_rng_with_rng, hash_msg}; use amcl::rand::RAND; use std::cmp::Ordering; use std::fmt; @@ -15,7 +14,7 @@ use std::ops::{Add, AddAssign, Index, IndexMut, Mul, Neg, RangeBounds, Sub, SubA use std::slice::Iter; use serde::de::{Deserialize, Deserializer, Error as DError, Visitor}; -use serde::ser::{Error as SError, Serialize, Serializer}; +use serde::ser::{Serialize, Serializer}; use crate::rayon::iter::IntoParallelRefMutIterator; use rayon::prelude::*; @@ -47,7 +46,7 @@ impl fmt::Display for FieldElement { impl Hash for FieldElement { fn hash(&self, state: &mut H) { - let mut bytes: [u8; FieldElement_SIZE] = [0; FieldElement_SIZE]; + let mut bytes: [u8; FIELD_ELEMENT_SIZE] = [0; FIELD_ELEMENT_SIZE]; self.write_to_slice_unchecked(&mut bytes); state.write(&bytes) } @@ -118,31 +117,31 @@ impl FieldElement { /// Return bytes in MSB form pub fn to_bytes(&self) -> Vec { - let mut bytes: [u8; FieldElement_SIZE] = [0; FieldElement_SIZE]; + let mut bytes: [u8; FIELD_ELEMENT_SIZE] = [0; FIELD_ELEMENT_SIZE]; self.write_to_slice_unchecked(&mut bytes); bytes.to_vec() } /// Expects bytes in MSB form pub fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != FieldElement_SIZE { + if bytes.len() != FIELD_ELEMENT_SIZE { return Err(SerzDeserzError::FieldElementBytesIncorrectSize( bytes.len(), - FieldElement_SIZE, + FIELD_ELEMENT_SIZE, )); } let mut n = BigNum::frombytes(bytes); - n.rmod(&CurveOrder); + n.rmod(&CURVE_ORDER); Ok(Self { value: n }) } /// Writes bytes in MSB form to given slice. Raises exception when given slice is not of /// desired length. pub fn write_to_slice(&self, target: &mut [u8]) -> Result<(), SerzDeserzError> { - if target.len() != FieldElement_SIZE { + if target.len() != FIELD_ELEMENT_SIZE { return Err(SerzDeserzError::FieldElementBytesIncorrectSize( target.len(), - FieldElement_SIZE, + FIELD_ELEMENT_SIZE, )); } self.write_to_slice_unchecked(target); @@ -158,7 +157,7 @@ impl FieldElement { pub fn to_bignum(&self) -> BigNum { let mut v = self.value.clone(); - v.rmod(&CurveOrder); + v.rmod(&CURVE_ORDER); v } @@ -177,31 +176,31 @@ impl FieldElement { pub fn add_assign_(&mut self, b: &Self) { // Not using `self.plus` to avoid cloning. Breaking the abstraction a bit for performance. self.value.add(&b.value); - self.value.rmod(&CurveOrder); + self.value.rmod(&CURVE_ORDER); } /// Subtract a field element from itself. `self = self - b` pub fn sub_assign_(&mut self, b: &Self) { // Not using `self.minus` to avoid cloning. Breaking the abstraction a bit for performance. - let neg_b = BigNum::modneg(&b.value, &CurveOrder); + let neg_b = BigNum::modneg(&b.value, &CURVE_ORDER); self.value.add(&neg_b); - self.value.rmod(&CurveOrder); + self.value.rmod(&CURVE_ORDER); } /// Return sum of a field element and itself. `self + b` pub fn plus(&self, b: &Self) -> Self { let mut sum = self.value.clone(); sum.add(&b.value); - sum.rmod(&CurveOrder); + sum.rmod(&CURVE_ORDER); sum.into() } /// Return difference of a field element and itself. `self - b` pub fn minus(&self, b: &Self) -> Self { let mut sum = self.value.clone(); - let neg_b = BigNum::modneg(&b.value, &CurveOrder); + let neg_b = BigNum::modneg(&b.value, &CURVE_ORDER); sum.add(&neg_b); - sum.rmod(&CurveOrder); + sum.rmod(&CURVE_ORDER); sum.into() } @@ -218,10 +217,10 @@ impl FieldElement { Self::reduce_dmod_curve_order(&d).into() } - /// Exponentiation modulo curve order, i.e. self^exp % CurveOrder + /// Exponentiation modulo curve order, i.e. self^exp % CURVE_ORDER pub fn pow(&self, exp: &Self) -> Self { let mut base = self.value.clone(); - let res = base.powmod(&exp.value, &CurveOrder); + let res = base.powmod(&exp.value, &CURVE_ORDER); res.into() } @@ -243,7 +242,7 @@ impl FieldElement { return Self::zero(); } let mut inv = self.value.clone(); - inv.invmodp(&CurveOrder); + inv.invmodp(&CURVE_ORDER); inv.into() } @@ -252,7 +251,7 @@ impl FieldElement { if self.is_zero() { self.value = BigNum::new(); } else { - self.value.invmodp(&CurveOrder); + self.value.invmodp(&CURVE_ORDER); } } @@ -311,7 +310,7 @@ impl FieldElement { for mut bit_vec in bit_vecs.drain(..) { let len = bit_vec.len(); bits.append(&mut bit_vec); - bits.append(&mut vec![0; BigNumBits - len]); + bits.append(&mut vec![0; BIG_NUM_BITS - len]); } bits } @@ -320,21 +319,21 @@ impl FieldElement { fn random_field_element_using_rng(rng: &mut R) -> BigNum { // initialise from at least 128 byte string of raw random entropy let entropy_size = 256; - let mut r = get_seeded_RNG_with_rng(entropy_size, rng); - Self::get_big_num_from_RAND(&mut r) + let mut r = get_seeded_rng_with_rng(entropy_size, rng); + Self::get_big_num_from_rand(&mut r) } fn random_field_element() -> BigNum { // initialise from at least 128 byte string of raw random entropy let entropy_size = 256; - let mut r = get_seeded_RNG(entropy_size); - Self::get_big_num_from_RAND(&mut r) + let mut r = get_seeded_rng(entropy_size); + Self::get_big_num_from_rand(&mut r) } - fn get_big_num_from_RAND(r: &mut RAND) -> BigNum { - let mut n = BigNum::randomnum(&BigNum::new_big(&CurveOrder), r); + fn get_big_num_from_rand(r: &mut RAND) -> BigNum { + let mut n = BigNum::randomnum(&BigNum::new_big(&CURVE_ORDER), r); while n.iszilch() { - n = BigNum::randomnum(&BigNum::new_big(&CurveOrder), r); + n = BigNum::randomnum(&BigNum::new_big(&CURVE_ORDER), r); } n } @@ -465,14 +464,14 @@ impl FieldElement { /// Create big number from hex string in big endian pub fn from_hex(s: String) -> Result { let mut f = Self::parse_hex_as_bignum(s)?; - f.rmod(&CurveOrder); + f.rmod(&CURVE_ORDER); Ok(f.into()) } /// Useful for reducing product of BigNums. Uses Barrett reduction pub fn reduce_dmod_curve_order(x: &DoubleBigNum) -> BigNum { - let (k, u, v) = (*BarrettRedc_k, *BarrettRedc_u, *BarrettRedc_v); - barrett_reduction(&x, &CurveOrder, k, &u, &v) + let (k, u, v) = (*BARRETT_REDC_K, *BARRETT_REDC_U, *BARRETT_REDC_V); + barrett_reduction(&x, &CURVE_ORDER, k, &u, &v) } /// Parse given hex string as BigNum in constant time. @@ -484,15 +483,15 @@ impl FieldElement { let mut val = val; // Given hex cannot be bigger than max byte size - if val.len() > FieldElement_SIZE * 2 { + if val.len() > FIELD_ELEMENT_SIZE * 2 { return Err(SerzDeserzError::FieldElementBytesIncorrectSize( val.len(), - FieldElement_SIZE, + FIELD_ELEMENT_SIZE, )); } // Pad the string for constant time parsing. - while val.len() < FieldElement_SIZE * 2 { + while val.len() < FIELD_ELEMENT_SIZE * 2 { val.insert(0, '0'); } @@ -583,10 +582,10 @@ impl From for FieldElement { } } -impl From<&[u8; FieldElement_SIZE]> for FieldElement { - fn from(x: &[u8; FieldElement_SIZE]) -> Self { +impl From<&[u8; FIELD_ELEMENT_SIZE]> for FieldElement { + fn from(x: &[u8; FIELD_ELEMENT_SIZE]) -> Self { let mut n = BigNum::frombytes(x); - n.rmod(&CurveOrder); + n.rmod(&CURVE_ORDER); Self { value: n } } } @@ -1026,7 +1025,7 @@ mod test { for _ in 0..100 { let x = FieldElement::random_using_rng(&mut rng); - let mut bytes_x: [u8; FieldElement_SIZE] = [0; FieldElement_SIZE]; + let mut bytes_x: [u8; FIELD_ELEMENT_SIZE] = [0; FIELD_ELEMENT_SIZE]; x.write_to_slice(&mut bytes_x).unwrap(); let y = FieldElement::from(&bytes_x); assert_eq!(x, y); @@ -1289,11 +1288,11 @@ mod test { #[test] fn test_to_bits() { let mut bits = vec![0, 1, 0, 1]; - bits.append(&mut vec![0; BigNumBits - 4]); + bits.append(&mut vec![0; BIG_NUM_BITS - 4]); assert_eq!(FieldElement::from(10u32).to_bits(), bits); let mut bits = vec![0, 0, 1, 0, 0, 1, 1]; - bits.append(&mut vec![0; BigNumBits - 7]); + bits.append(&mut vec![0; BIG_NUM_BITS - 7]); assert_eq!(FieldElement::from(100u32).to_bits(), bits); let mut c = vec![0i64; NLEN]; @@ -1301,9 +1300,9 @@ mod test { c[1] = 100; let m: FieldElement = BigNum::new_ints(&c).into(); let mut bits = vec![0, 1]; - bits.append(&mut vec![0; BigNumBits - 2]); + bits.append(&mut vec![0; BIG_NUM_BITS - 2]); bits.append(&mut vec![0, 0, 1, 0, 0, 1, 1]); - bits.append(&mut vec![0; BigNumBits - 7]); + bits.append(&mut vec![0; BIG_NUM_BITS - 7]); assert_eq!(m.to_bits(), bits); } @@ -1489,15 +1488,15 @@ mod test { let mut o1 = vec![]; let mut o2 = vec![]; - let (k, u, v) = (*BarrettRedc_k, *BarrettRedc_u, *BarrettRedc_v); + let (k, u, v) = (*BARRETT_REDC_K, *BARRETT_REDC_U, *BARRETT_REDC_V); let mut start = Instant::now(); for i in 0..count { let mut a = l[i].clone(); - a.rmod(&CurveOrder); + a.rmod(&CURVE_ORDER); let mut b = r[i].clone(); - b.rmod(&CurveOrder); + b.rmod(&CURVE_ORDER); let d = BigNum::mul(&a, &b); - o1.push(barrett_reduction(&d, &CurveOrder, k, &u, &v)); + o1.push(barrett_reduction(&d, &CURVE_ORDER, k, &u, &v)); } println!("Mul1 for {} elems = {:?}", count, start.elapsed()); @@ -1506,7 +1505,7 @@ mod test { let a = l[i].clone(); let b = r[i].clone(); let d = BigNum::mul(&a, &b); - o2.push(barrett_reduction(&d, &CurveOrder, k, &u, &v)); + o2.push(barrett_reduction(&d, &CURVE_ORDER, k, &u, &v)); } println!("Mul2 for {} elems = {:?}", count, start.elapsed()); @@ -1517,11 +1516,11 @@ mod test { let mut x = BigNum::new_int(1isize); start = Instant::now(); for i in 0..count { - x.rmod(&CurveOrder); + x.rmod(&CURVE_ORDER); let mut b = o1[i].clone(); - b.rmod(&CurveOrder); + b.rmod(&CURVE_ORDER); let d = BigNum::mul(&x, &b); - x = barrett_reduction(&d, &CurveOrder, k, &u, &v); + x = barrett_reduction(&d, &CURVE_ORDER, k, &u, &v); } println!("Mul1 all for {} elems = {:?}", count, start.elapsed()); @@ -1530,7 +1529,7 @@ mod test { for i in 0..count { let b = o2[i].clone(); let d = BigNum::mul(&y, &b); - y = barrett_reduction(&d, &CurveOrder, k, &u, &v); + y = barrett_reduction(&d, &CURVE_ORDER, k, &u, &v); } println!("Mul2 all for {} elems = {:?}", count, start.elapsed()); @@ -1562,13 +1561,13 @@ mod test { let start = Instant::now(); for i in 0..count { - BigNum::modmul(&nums[i], &nums[i], &CurveOrder); + BigNum::modmul(&nums[i], &nums[i], &CURVE_ORDER); } println!("Mul time for {} big nums = {:?}", count, start.elapsed()); let start = Instant::now(); for i in 0..count { - BigNum::modsqr(&nums[i], &CurveOrder); + BigNum::modsqr(&nums[i], &CURVE_ORDER); } println!("Sqr time for {} big nums = {:?}", count, start.elapsed()); } @@ -1591,13 +1590,13 @@ mod test { let mut h = r1.to_hex(); // Make hex string bigger h.insert(0, '0'); - assert!(h.len() > FieldElement_SIZE * 2); + assert!(h.len() > FIELD_ELEMENT_SIZE * 2); assert!(FieldElement::parse_hex_as_bignum(h.clone()).is_err()); let mut h = r1.to_hex(); // Add non hex character h = h.replacen("0", "G", 1); - assert_eq!(h.len(), FieldElement_SIZE * 2); + assert_eq!(h.len(), FIELD_ELEMENT_SIZE * 2); assert!(FieldElement::parse_hex_as_bignum(h.clone()).is_err()); } diff --git a/src/group_elem.rs b/src/group_elem.rs index 069bc49..428d27a 100644 --- a/src/group_elem.rs +++ b/src/group_elem.rs @@ -1,9 +1,8 @@ use rand::{CryptoRng, RngCore}; use crate::errors::{SerzDeserzError, ValueError}; -use crate::field_elem::{FieldElement, FieldElementVector}; +use crate::field_elem::FieldElement; -use rayon::prelude::*; use std::slice::Iter; #[macro_export] @@ -145,6 +144,7 @@ macro_rules! impl_group_elem_traits { } } + #[allow(unused_mut)] impl fmt::Display for $group_element { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut c = self.value.clone(); @@ -408,8 +408,8 @@ macro_rules! impl_group_element_lookup_table { } impl<'a> From<&'a $group_element> for $name { - fn from(A: &'a $group_element) -> Self { - let mut Ai: [$group_element; 8] = [ + fn from(a: &'a $group_element) -> Self { + let mut a_i: [$group_element; 8] = [ $group_element::new(), $group_element::new(), $group_element::new(), @@ -419,13 +419,13 @@ macro_rules! impl_group_element_lookup_table { $group_element::new(), $group_element::new(), ]; - let A2 = A.double(); - Ai[0] = A.clone(); + let a_2 = a.double(); + a_i[0] = a.clone(); for i in 0..7 { - Ai[i + 1] = &Ai[i] + &A2; + a_i[i + 1] = &a_i[i] + &a_2; } // Now Ai = [A, 3A, 5A, 7A, 9A, 11A, 13A, 15A] - Self(Ai) + Self(a_i) } } }; @@ -664,7 +664,7 @@ macro_rules! impl_group_elem_vec_product_ops { group_elems: Vec<&$group_element>, field_elems: Vec<&FieldElement>, ) -> Result<$group_element, ValueError> { - Self::multi_scalar_mul_var_time_from_ref_vecs(group_elems, field_elems) + Self::multi_scalar_mul_var_time_without_precomputation(group_elems, field_elems) } /// Calculates Hadamard product of 2 group element vectors. @@ -927,9 +927,9 @@ macro_rules! impl_group_elem_vec_conversions { #[cfg(test)] mod test { use super::*; - use crate::constants::GroupG1_SIZE; + use crate::constants::GROUP_G1_SIZE; #[cfg(any(feature = "bls381", feature = "bn254"))] - use crate::constants::{GroupG2_SIZE, GroupGT_SIZE}; + use crate::constants::{GROUP_G2_SIZE, GROUP_GT_SIZE}; #[cfg(any(feature = "bls381", feature = "bn254"))] use crate::extension_field_gt::GT; use crate::group_elem_g1::{G1LookupTable, G1Vector, G1}; @@ -966,7 +966,7 @@ mod test { }; } - to_and_fro_bytes!(G1, GroupG1_SIZE); + to_and_fro_bytes!(G1, GROUP_G1_SIZE); #[cfg(any(feature = "bls381", feature = "bn254"))] to_and_fro_bytes!(G2, GroupG2_SIZE); #[cfg(any(feature = "bls381", feature = "bn254"))] diff --git a/src/group_elem_g1.rs b/src/group_elem_g1.rs index 7bd6ba4..3e82b26 100644 --- a/src/group_elem_g1.rs +++ b/src/group_elem_g1.rs @@ -1,4 +1,4 @@ -use crate::constants::{CurveOrder, GroupG1_SIZE}; +use crate::constants::{CURVE_ORDER, GROUP_G1_SIZE}; use crate::errors::{SerzDeserzError, ValueError}; use crate::field_elem::{FieldElement, FieldElementVector}; use crate::group_elem::{GroupElement, GroupElementVector}; @@ -13,7 +13,7 @@ use std::slice::Iter; use crate::rayon::iter::IntoParallelRefMutIterator; use rayon::prelude::*; use serde::de::{Deserialize, Deserializer, Error as DError, Visitor}; -use serde::ser::{Error as SError, Serialize, Serializer}; +use serde::ser::{Serialize, Serializer}; use std::str::{FromStr, SplitWhitespace}; use zeroize::Zeroize; @@ -53,26 +53,26 @@ impl GroupElement for G1 { } fn to_bytes(&self) -> Vec { - let mut bytes: [u8; GroupG1_SIZE] = [0; GroupG1_SIZE]; + let mut bytes: [u8; GROUP_G1_SIZE] = [0; GROUP_G1_SIZE]; self.write_to_slice_unchecked(&mut bytes); bytes.to_vec() } fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != GroupG1_SIZE { + if bytes.len() != GROUP_G1_SIZE { return Err(SerzDeserzError::G1BytesIncorrectSize( bytes.len(), - GroupG1_SIZE, + GROUP_G1_SIZE, )); } Ok(GroupG1::frombytes(bytes).into()) } fn write_to_slice(&self, target: &mut [u8]) -> Result<(), SerzDeserzError> { - if target.len() != GroupG1_SIZE { + if target.len() != GROUP_G1_SIZE { return Err(SerzDeserzError::G1BytesIncorrectSize( target.len(), - GroupG1_SIZE, + GROUP_G1_SIZE, )); } self.write_to_slice_unchecked(target); @@ -125,9 +125,9 @@ impl GroupElement for G1 { fn from_hex(s: String) -> Result { let mut iter = s.split_whitespace(); - let x = parse_hex_as_FP(&mut iter)?; - let y = parse_hex_as_FP(&mut iter)?; - let z = parse_hex_as_FP(&mut iter)?; + let x = parse_hex_as_fp(&mut iter)?; + let y = parse_hex_as_fp(&mut iter)?; + let z = parse_hex_as_fp(&mut iter)?; let mut value = GroupG1::new(); value.setpx(x); value.setpy(y); @@ -146,7 +146,7 @@ impl GroupElement for G1 { } fn has_correct_order(&self) -> bool { - return self.value.mul(&CurveOrder).is_infinity(); + return self.value.mul(&CURVE_ORDER).is_infinity(); } } @@ -163,7 +163,7 @@ impl G1 { impl_group_elem_traits!(G1, GroupG1); -impl_group_elem_conversions!(G1, GroupG1, GroupG1_SIZE); +impl_group_elem_conversions!(G1, GroupG1, GROUP_G1_SIZE); impl_group_elem_ops!(G1); @@ -171,7 +171,7 @@ impl_scalar_mul_ops!(G1); impl_group_element_lookup_table!(G1, G1LookupTable); -/// Represents an element of the sub-group of the elliptic curve over the prime field +// Represents an element of the sub-group of the elliptic curve over the prime field impl_optmz_scalar_mul_ops!(G1, GroupG1, G1LookupTable); #[derive(Clone, Debug, Serialize, Deserialize)] @@ -186,7 +186,7 @@ impl_group_elem_vec_product_ops!(G1, G1Vector, G1LookupTable); impl_group_elem_vec_conversions!(G1, G1Vector); /// Parse given hex string as FP -pub fn parse_hex_as_FP(iter: &mut SplitWhitespace) -> Result { +pub fn parse_hex_as_fp(iter: &mut SplitWhitespace) -> Result { // Logic almost copied from AMCL but with error handling and constant time execution. // Constant time is important as hex is used during serialization and deserialization. // A seemingly effortless solution is to filter string for errors and pad with 0s before diff --git a/src/group_elem_g2.rs b/src/group_elem_g2.rs index cde21b4..2be7e91 100644 --- a/src/group_elem_g2.rs +++ b/src/group_elem_g2.rs @@ -1,4 +1,4 @@ -use crate::constants::{CurveOrder, GroupG2_SIZE}; +use crate::constants::{CURVE_ORDER, GROUP_G2_SIZE}; use crate::errors::{SerzDeserzError, ValueError}; use crate::field_elem::{FieldElement, FieldElementVector}; use crate::group_elem::{GroupElement, GroupElementVector}; @@ -11,11 +11,11 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::slice::Iter; -use crate::group_elem_g1::parse_hex_as_FP; +use crate::group_elem_g1::parse_hex_as_fp; use crate::rayon::iter::IntoParallelRefMutIterator; use rayon::prelude::*; use serde::de::{Deserialize, Deserializer, Error as DError, Visitor}; -use serde::ser::{Error as SError, Serialize, Serializer}; +use serde::ser::{Serialize, Serializer}; use std::str::SplitWhitespace; use zeroize::Zeroize; @@ -55,26 +55,26 @@ impl GroupElement for G2 { } fn to_bytes(&self) -> Vec { - let mut bytes: [u8; GroupG2_SIZE] = [0; GroupG2_SIZE]; + let mut bytes: [u8; GROUP_G2_SIZE] = [0; GROUP_G2_SIZE]; self.write_to_slice_unchecked(&mut bytes); bytes.to_vec() } fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != GroupG2_SIZE { + if bytes.len() != GROUP_G2_SIZE { return Err(SerzDeserzError::G2BytesIncorrectSize( bytes.len(), - GroupG2_SIZE, + GROUP_G2_SIZE, )); } Ok(GroupG2::frombytes(bytes).into()) } fn write_to_slice(&self, target: &mut [u8]) -> Result<(), SerzDeserzError> { - if target.len() != GroupG2_SIZE { + if target.len() != GROUP_G2_SIZE { return Err(SerzDeserzError::G2BytesIncorrectSize( target.len(), - GroupG2_SIZE, + GROUP_G2_SIZE, )); } self.write_to_slice_unchecked(target); @@ -127,9 +127,9 @@ impl GroupElement for G2 { fn from_hex(s: String) -> Result { let mut iter = s.split_whitespace(); - let x = parse_hex_as_FP2(&mut iter)?; - let y = parse_hex_as_FP2(&mut iter)?; - let z = parse_hex_as_FP2(&mut iter)?; + let x = parse_hex_as_fp2(&mut iter)?; + let y = parse_hex_as_fp2(&mut iter)?; + let z = parse_hex_as_fp2(&mut iter)?; let mut value = GroupG2::new(); value.setpx(x); value.setpy(y); @@ -148,18 +148,18 @@ impl GroupElement for G2 { } fn has_correct_order(&self) -> bool { - return self.value.mul(&CurveOrder).is_infinity(); + return self.value.mul(&CURVE_ORDER).is_infinity(); } } /// Parse given hex string as FP2 -pub fn parse_hex_as_FP2(iter: &mut SplitWhitespace) -> Result { +pub fn parse_hex_as_fp2(iter: &mut SplitWhitespace) -> Result { // Logic almost copied from AMCL but with error handling and constant time execution. // Constant time is important as hex is used during serialization and deserialization. // A seemingly effortless solution is to filter string for errors and pad with 0s before // passing to AMCL but that would be expensive as the string is scanned twice - let a = parse_hex_as_FP(iter)?; - let b = parse_hex_as_FP(iter)?; + let a = parse_hex_as_fp(iter)?; + let b = parse_hex_as_fp(iter)?; let mut fp2 = FP2::new(); fp2.seta(a); fp2.setb(b); @@ -168,7 +168,7 @@ pub fn parse_hex_as_FP2(iter: &mut SplitWhitespace) -> Result [u8; FieldElement_SIZE] { +pub fn hash_msg(msg: &[u8]) -> [u8; FIELD_ELEMENT_SIZE] { let mut hasher = Shake256::default(); hasher.input(&msg); - let mut h: [u8; FieldElement_SIZE] = [0; FieldElement_SIZE]; + let mut h: [u8; FIELD_ELEMENT_SIZE] = [0; FIELD_ELEMENT_SIZE]; hasher.xof_result().read(&mut h); h } -pub fn get_seeded_RNG_with_rng(entropy_size: usize, rng: &mut R) -> RAND { +pub fn get_seeded_rng_with_rng(entropy_size: usize, rng: &mut R) -> RAND { // initialise from at least 128 byte string of raw random entropy let mut entropy = vec![0; entropy_size]; rng.fill_bytes(&mut entropy.as_mut_slice()); - get_RAND(entropy_size, entropy.as_slice()) + get_rand(entropy_size, entropy.as_slice()) } -pub fn get_seeded_RNG(entropy_size: usize) -> RAND { +pub fn get_seeded_rng(entropy_size: usize) -> RAND { let mut entropy = vec![0; entropy_size]; let mut rng = rand::thread_rng(); rng.fill_bytes(&mut entropy.as_mut_slice()); - get_RAND(entropy_size, entropy.as_slice()) + get_rand(entropy_size, entropy.as_slice()) } -fn get_RAND(entropy_size: usize, entropy: &[u8]) -> RAND { +fn get_rand(entropy_size: usize, entropy: &[u8]) -> RAND { let mut r = RAND::new(); r.clean(); r.seed(entropy_size, &entropy); @@ -141,14 +140,14 @@ fn __barrett_reduction__(x: &BigNum, modulus: &BigNum, k: usize, u: &BigNum, v: pub fn barrett_reduction_params(modulus: &BigNum) -> (usize, BigNum, BigNum) { let k = modulus.nbits(); - // u = floor(2^2k/CurveOrder) + // u = floor(2^2k/CURVE_ORDER) let mut u = DoubleBigNum::new(); u.w[0] = 1; // `u.shl(2*k)` crashes, so perform shl(k) twice u.shl(k); u.shl(k); // div returns floored value - let u = u.div(&CurveOrder); + let u = u.div(&CURVE_ORDER); // v = 2^(k+1) let mut v = BigNum::new_int(1isize); @@ -180,7 +179,7 @@ mod test { let mut res_mul = BIG::new_int(1 as isize); let mut start = Instant::now(); for b in &bigs { - res_mul = BigNum::modmul(&res_mul, &b, &CurveOrder); + res_mul = BigNum::modmul(&res_mul, &b, &CURVE_ORDER); } println!( "Multiplication time for {} BIGs = {:?}", @@ -216,12 +215,12 @@ mod test { start = Instant::now(); for b in &bigs { let mut i = b.clone(); - i.invmodp(&CurveOrder); + i.invmodp(&CURVE_ORDER); inverses_b.push(i); } println!("Inverse time for {} BIGs = {:?}", count, start.elapsed()); for i in 0..count { - let r = BigNum::modmul(&inverses_b[i], &bigs[i], &CurveOrder); + let r = BigNum::modmul(&inverses_b[i], &bigs[i], &CURVE_ORDER); assert_eq!(BigNum::comp(&r, &BigNum::new_int(1 as isize)), 0); } @@ -244,7 +243,7 @@ mod test { let mut r = bigs[0]; for i in 0..c { r.add(&bigs[i]); - r.rmod(&CurveOrder); + r.rmod(&CURVE_ORDER); } println!("Addition time for {} BIGs = {:?}", c, start.elapsed()); @@ -297,11 +296,11 @@ mod test { #[test] fn timing_barrett_reduction() { - //let (k, u, v) = barrett_reduction_params(&CurveOrder); + //let (k, u, v) = barrett_reduction_params(&CURVE_ORDER); let (k, u, v) = ( - *constants::BarrettRedc_k, - *constants::BarrettRedc_u, - *constants::BarrettRedc_v, + *constants::BARRETT_REDC_K, + *constants::BARRETT_REDC_U, + *constants::BARRETT_REDC_V, ); let mut xs = vec![]; let mut reduced1 = vec![]; @@ -311,13 +310,13 @@ mod test { for _ in 0..count { let a: u32 = rng.gen(); let s = BigNum::new_int(a as isize); - let _x = CurveOrder.minus(&s); + let _x = CURVE_ORDER.minus(&s); xs.push(BigNum::mul(&_x, &_x)); } let mut start = Instant::now(); for x in &xs { - let r = barrett_reduction(&x, &CurveOrder, k, &u, &v); + let r = barrett_reduction(&x, &CURVE_ORDER, k, &u, &v); reduced1.push(r); } println!("Barrett time = {:?}", start.elapsed()); @@ -325,7 +324,7 @@ mod test { start = Instant::now(); for x in &xs { let mut y = x.clone(); - let z = y.dmod(&CurveOrder); + let z = y.dmod(&CURVE_ORDER); reduced2.push(z); } println!("Normal time = {:?}", start.elapsed()); @@ -338,9 +337,9 @@ mod test { #[test] fn timing_rmod_with_barrett_reduction() { let (k, u, v) = ( - *constants::BarrettRedc_k, - *constants::BarrettRedc_u, - *constants::BarrettRedc_v, + *constants::BARRETT_REDC_K, + *constants::BARRETT_REDC_U, + *constants::BARRETT_REDC_V, ); let count = 100; let elems: Vec<_> = (0..count).map(|_| FieldElement::random()).collect(); @@ -350,7 +349,7 @@ mod test { let mut start = Instant::now(); for i in 0..count { sum = BigNum::plus(&sum, &bigs[i]); - sum.rmod(&CurveOrder) + sum.rmod(&CURVE_ORDER) } println!("rmod time = {:?}", start.elapsed()); @@ -358,7 +357,7 @@ mod test { start = Instant::now(); for i in 0..count { sum_b = BigNum::plus(&sum_b, &bigs[i]); - sum_b = __barrett_reduction__(&sum_b, &CurveOrder, k, &u, &v) + sum_b = __barrett_reduction__(&sum_b, &CURVE_ORDER, k, &u, &v) } println!("Barrett time = {:?}", start.elapsed()); From 4e7928fe52a5fb23fc42f95853ff1df07e286008 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Sat, 21 Mar 2020 08:55:47 -0600 Subject: [PATCH 02/15] Add sgn0 Signed-off-by: Michael Lodder --- src/constants.rs | 6 ++++++ src/field_elem.rs | 28 ++++++++++++++++++++++++++++ src/lib.rs | 1 + src/signum.rs | 22 ++++++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 src/signum.rs diff --git a/src/constants.rs b/src/constants.rs index e9f4933..d566d37 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -16,6 +16,12 @@ pub const GROUP_G1_SIZE: usize = (2 * MODBYTES + 1) as usize; lazy_static! { pub static ref GENERATOR_G1: GroupG1 = GroupG1::generator(); pub static ref CURVE_ORDER: BigNum = BigNum::new_ints(&rom::CURVE_ORDER); + pub static ref CURVE_ORDER_MINUS_1_DIV_2: BigNum = { + let mut order = BigNum::new_ints(&rom::CURVE_ORDER); + order.dec(1); + order.shr(1); + order + }; pub static ref CURVE_ORDER_BIT_SIZE: usize = CURVE_ORDER.nbits(); pub static ref FIELD_ELEMENT_ZERO: BigNum = BigNum::new(); pub static ref BARRETT_REDC_K: usize = CURVE_ORDER.nbits(); diff --git a/src/field_elem.rs b/src/field_elem.rs index 4bcc78a..2fafed2 100644 --- a/src/field_elem.rs +++ b/src/field_elem.rs @@ -2,8 +2,10 @@ use rand::{CryptoRng, RngCore}; use crate::constants::{ BARRETT_REDC_K, BARRETT_REDC_U, BARRETT_REDC_V, BIG_NUM_BITS, CURVE_ORDER, FIELD_ELEMENT_SIZE, NLEN, + CURVE_ORDER_MINUS_1_DIV_2 }; use crate::errors::{SerzDeserzError, ValueError}; +use crate::signum::Sgn0; use crate::types::{BigNum, DoubleBigNum, Limb}; use crate::utils::{barrett_reduction, get_seeded_rng, get_seeded_rng_with_rng, hash_msg}; use amcl::rand::RAND; @@ -508,6 +510,32 @@ impl FieldElement { } return Ok(res); } + + ///If c is False, cmove returns self, otherwise it returns b. + pub fn cmove(&self, b: &Self, c: bool) -> Self { + let mut res = self.value.clone(); + res.cmove(&b.value, c as isize); + res.into() + } + + /// returns either +1 or -1 indicating the + /// "sign" of x, where sgn0(x) == -1 just when x is "negative". In + /// other words, this function always considers 0 to be positive. + pub fn sgn0(&self) -> Sgn0 { + if self.value > *CURVE_ORDER_MINUS_1_DIV_2 { + Sgn0::Negative + } else { + Sgn0::NonNegative + } + } + + pub fn negate_if(&self, sgn: Sgn0) -> Self { + if sgn == Sgn0::Negative { + -self.clone() + } else { + self.clone() + } + } } impl Serialize for FieldElement { diff --git a/src/lib.rs b/src/lib.rs index 1f8c8d2..7524a55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,7 @@ extern crate subtle_encoding; pub mod constants; pub mod types; +pub mod signum; #[macro_use] pub mod errors; diff --git a/src/signum.rs b/src/signum.rs new file mode 100644 index 0000000..0f27327 --- /dev/null +++ b/src/signum.rs @@ -0,0 +1,22 @@ +use std::ops::BitXor; + +#[derive(Debug, Eq, PartialEq)] +pub enum Sgn0 { + /// Either 0 or positive + NonNegative, + /// Neither 0 nor positive + Negative +} + +impl BitXor for Sgn0 { + type Output = Self; + + fn bitxor(self, rhs: Self) -> Self { + if self == rhs { + Sgn0::NonNegative + } else { + Sgn0::Negative + } + } +} + From 2426c46d9484385e110253d26c2d19c1c57e5b5d Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Sat, 21 Mar 2020 13:45:19 -0600 Subject: [PATCH 03/15] More fixing of warnings Signed-off-by: Michael Lodder --- src/extension_field_gt.rs | 3 +-- src/field_elem.rs | 11 +++++++---- src/group_elem.rs | 13 +++++++------ src/group_elem_g1.rs | 8 +++----- src/group_elem_g2.rs | 5 ++--- src/univar_poly.rs | 4 ++-- src/utils.rs | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/extension_field_gt.rs b/src/extension_field_gt.rs index 04e3510..1380085 100644 --- a/src/extension_field_gt.rs +++ b/src/extension_field_gt.rs @@ -257,8 +257,7 @@ impl Mul<>> for > { #[cfg(test)] mod test { use super::*; - use crate::group_elem_g1::G1Vector; - use std::time::{Duration, Instant}; + use std::time::Instant; #[test] fn test_unity() { diff --git a/src/field_elem.rs b/src/field_elem.rs index 2fafed2..18b9ab0 100644 --- a/src/field_elem.rs +++ b/src/field_elem.rs @@ -536,6 +536,10 @@ impl FieldElement { self.clone() } } + + pub const fn from_array(w: [Limb; NLEN]) -> FieldElement { + FieldElement { value: BigNum { w } } + } } impl Serialize for FieldElement { @@ -1041,11 +1045,10 @@ pub fn multiply_row_vector_with_matrix( #[cfg(test)] mod test { use super::*; - use amcl::bls381::big::BIG; use rand::Rng; use serde_json; use std::collections::{HashMap, HashSet}; - use std::time::{Duration, Instant}; + use std::time::Instant; #[test] fn test_to_and_from_bytes() { @@ -1496,10 +1499,10 @@ mod test { fn timing_field_elem_addition() { let count = 100; let points: Vec = (0..count).map(|_| FieldElement::random()).collect(); - let mut R = FieldElement::random(); + let mut r = FieldElement::random(); let start = Instant::now(); for i in 0..count { - R = &R + &points[i]; + r = &r + &points[i]; } println!("Addition time for {} elems = {:?}", count, start.elapsed()); } diff --git a/src/group_elem.rs b/src/group_elem.rs index 428d27a..d58ba61 100644 --- a/src/group_elem.rs +++ b/src/group_elem.rs @@ -928,6 +928,7 @@ macro_rules! impl_group_elem_vec_conversions { mod test { use super::*; use crate::constants::GROUP_G1_SIZE; + use crate::field_elem::FieldElementVector; #[cfg(any(feature = "bls381", feature = "bn254"))] use crate::constants::{GROUP_G2_SIZE, GROUP_GT_SIZE}; #[cfg(any(feature = "bls381", feature = "bn254"))] @@ -936,7 +937,7 @@ mod test { #[cfg(any(feature = "bls381", feature = "bn254"))] use crate::group_elem_g2::{G2LookupTable, G2Vector, G2}; use std::collections::{HashMap, HashSet}; - use std::time::{Duration, Instant}; + use std::time::Instant; #[test] fn test_to_and_from_bytes() { @@ -968,9 +969,9 @@ mod test { to_and_fro_bytes!(G1, GROUP_G1_SIZE); #[cfg(any(feature = "bls381", feature = "bn254"))] - to_and_fro_bytes!(G2, GroupG2_SIZE); + to_and_fro_bytes!(G2, GROUP_G2_SIZE); #[cfg(any(feature = "bls381", feature = "bn254"))] - to_and_fro_bytes!(GT, GroupGT_SIZE); + to_and_fro_bytes!(GT, GROUP_GT_SIZE); } #[test] @@ -1114,17 +1115,17 @@ mod test { macro_rules! add_mul { ( $group:ident ) => { let points: Vec<_> = (0..100).map(|_| $group::random()).collect(); - let mut R = $group::random(); + let mut r = $group::random(); let mut start = Instant::now(); for i in 0..count { - R = R + &points[i]; + r = r + &points[i]; } println!("Addition time for {} elems = {:?}", count, start.elapsed()); let fs: Vec<_> = (0..100).map(|_| FieldElement::random()).collect(); start = Instant::now(); for i in 0..count { - &points[i] * &fs[i]; + let _ = &points[i] * &fs[i]; } println!( "Scalar multiplication time for {} elems = {:?}", diff --git a/src/group_elem_g1.rs b/src/group_elem_g1.rs index 3e82b26..29a9bb3 100644 --- a/src/group_elem_g1.rs +++ b/src/group_elem_g1.rs @@ -213,17 +213,15 @@ pub fn parse_hex_as_fp(iter: &mut SplitWhitespace) -> Result Date: Sat, 21 Mar 2020 13:49:45 -0600 Subject: [PATCH 04/15] More comments Signed-off-by: Michael Lodder --- src/field_elem.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/field_elem.rs b/src/field_elem.rs index 18b9ab0..3f5f34f 100644 --- a/src/field_elem.rs +++ b/src/field_elem.rs @@ -537,6 +537,7 @@ impl FieldElement { } } + /// Use this instead of static ref and new_int. This allows for initialization at compile time pub const fn from_array(w: [Limb; NLEN]) -> FieldElement { FieldElement { value: BigNum { w } } } From a0d70843d41c861c82c0c8383439f69c737103fb Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Sat, 21 Mar 2020 14:03:34 -0600 Subject: [PATCH 05/15] Added modulus Signed-off-by: Michael Lodder --- src/constants.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/constants.rs b/src/constants.rs index d566d37..94913e8 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -15,6 +15,7 @@ pub const GROUP_G1_SIZE: usize = (2 * MODBYTES + 1) as usize; lazy_static! { pub static ref GENERATOR_G1: GroupG1 = GroupG1::generator(); + pub static ref MODULUS: BigNum = BigNum::new_ints(&rom::MODULUS); pub static ref CURVE_ORDER: BigNum = BigNum::new_ints(&rom::CURVE_ORDER); pub static ref CURVE_ORDER_MINUS_1_DIV_2: BigNum = { let mut order = BigNum::new_ints(&rom::CURVE_ORDER); From 9ca2b2a17456769b3116d3a40828e6b4520ec995 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Sat, 21 Mar 2020 14:51:02 -0600 Subject: [PATCH 06/15] Change to use reduction via modulus Signed-off-by: Michael Lodder --- src/constants.rs | 13 +++++---- src/field_elem.rs | 68 ++++++++++++++++++++++---------------------- src/group_elem_g1.rs | 4 +-- src/group_elem_g2.rs | 4 +-- src/utils.rs | 26 ++++++++--------- 5 files changed, 58 insertions(+), 57 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 94913e8..82124f0 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -16,18 +16,19 @@ pub const GROUP_G1_SIZE: usize = (2 * MODBYTES + 1) as usize; lazy_static! { pub static ref GENERATOR_G1: GroupG1 = GroupG1::generator(); pub static ref MODULUS: BigNum = BigNum::new_ints(&rom::MODULUS); + pub static ref MODULUS_BITS: usize = MODULUS.nbits(); pub static ref CURVE_ORDER: BigNum = BigNum::new_ints(&rom::CURVE_ORDER); - pub static ref CURVE_ORDER_MINUS_1_DIV_2: BigNum = { - let mut order = BigNum::new_ints(&rom::CURVE_ORDER); + pub static ref MODULUS_MINUS_1_DIV_2: BigNum = { + let mut order = BigNum::new_ints(&rom::MODULUS); order.dec(1); order.shr(1); order }; pub static ref CURVE_ORDER_BIT_SIZE: usize = CURVE_ORDER.nbits(); pub static ref FIELD_ELEMENT_ZERO: BigNum = BigNum::new(); - pub static ref BARRETT_REDC_K: usize = CURVE_ORDER.nbits(); + pub static ref BARRETT_REDC_K: usize = MODULUS.nbits(); pub static ref BARRETT_REDC_U: BigNum = { - let k = CURVE_ORDER.nbits(); + let k = MODULUS.nbits(); let mut u = DoubleBigNum::new(); u.w[0] = 1; // `u.shl(2*k)` crashes, so perform shl(k) twice @@ -35,11 +36,11 @@ lazy_static! { u.shl(k); // div returns floored value - u.div(&CURVE_ORDER) + u.div(&MODULUS) }; pub static ref BARRETT_REDC_V: BigNum = { - let k = CURVE_ORDER.nbits(); + let k = MODULUS.nbits(); let mut v = BigNum::new_int(1isize); v.shl(k+1); v diff --git a/src/field_elem.rs b/src/field_elem.rs index 3f5f34f..a9bd2e2 100644 --- a/src/field_elem.rs +++ b/src/field_elem.rs @@ -1,8 +1,8 @@ use rand::{CryptoRng, RngCore}; use crate::constants::{ - BARRETT_REDC_K, BARRETT_REDC_U, BARRETT_REDC_V, BIG_NUM_BITS, CURVE_ORDER, FIELD_ELEMENT_SIZE, NLEN, - CURVE_ORDER_MINUS_1_DIV_2 + BARRETT_REDC_K, BARRETT_REDC_U, BARRETT_REDC_V, BIG_NUM_BITS, MODULUS, FIELD_ELEMENT_SIZE, NLEN, + MODULUS_MINUS_1_DIV_2 }; use crate::errors::{SerzDeserzError, ValueError}; use crate::signum::Sgn0; @@ -133,7 +133,7 @@ impl FieldElement { )); } let mut n = BigNum::frombytes(bytes); - n.rmod(&CURVE_ORDER); + n.rmod(&MODULUS); Ok(Self { value: n }) } @@ -159,7 +159,7 @@ impl FieldElement { pub fn to_bignum(&self) -> BigNum { let mut v = self.value.clone(); - v.rmod(&CURVE_ORDER); + v.rmod(&MODULUS); v } @@ -178,51 +178,51 @@ impl FieldElement { pub fn add_assign_(&mut self, b: &Self) { // Not using `self.plus` to avoid cloning. Breaking the abstraction a bit for performance. self.value.add(&b.value); - self.value.rmod(&CURVE_ORDER); + self.value.rmod(&MODULUS); } /// Subtract a field element from itself. `self = self - b` pub fn sub_assign_(&mut self, b: &Self) { // Not using `self.minus` to avoid cloning. Breaking the abstraction a bit for performance. - let neg_b = BigNum::modneg(&b.value, &CURVE_ORDER); + let neg_b = BigNum::modneg(&b.value, &MODULUS); self.value.add(&neg_b); - self.value.rmod(&CURVE_ORDER); + self.value.rmod(&MODULUS); } /// Return sum of a field element and itself. `self + b` pub fn plus(&self, b: &Self) -> Self { let mut sum = self.value.clone(); sum.add(&b.value); - sum.rmod(&CURVE_ORDER); + sum.rmod(&MODULUS); sum.into() } /// Return difference of a field element and itself. `self - b` pub fn minus(&self, b: &Self) -> Self { let mut sum = self.value.clone(); - let neg_b = BigNum::modneg(&b.value, &CURVE_ORDER); + let neg_b = BigNum::modneg(&b.value, &MODULUS); sum.add(&neg_b); - sum.rmod(&CURVE_ORDER); + sum.rmod(&MODULUS); sum.into() } /// Multiply 2 field elements modulus the order of the curve. - /// (field_element_a * field_element_b) % curve_order + /// (field_element_a * field_element_b) % modulus pub fn multiply(&self, b: &Self) -> Self { let d = BigNum::mul(&self.value, &b.value); Self::reduce_dmod_curve_order(&d).into() } - /// Calculate square of a field element modulo the curve order, i.e `a^2 % curve_order` + /// Calculate square of a field element modulo the curve order, i.e `a^2 % MODULUS` pub fn square(&self) -> Self { let d = BigNum::sqr(&self.value); Self::reduce_dmod_curve_order(&d).into() } - /// Exponentiation modulo curve order, i.e. self^exp % CURVE_ORDER + /// Exponentiation modulo curve order, i.e. self^exp % MODULUS pub fn pow(&self, exp: &Self) -> Self { let mut base = self.value.clone(); - let res = base.powmod(&exp.value, &CURVE_ORDER); + let res = base.powmod(&exp.value, &MODULUS); res.into() } @@ -237,14 +237,14 @@ impl FieldElement { self.value = zero.minus(&self).value; } - /// Calculate inverse of a field element modulo the curve order, i.e `a^-1 % curve_order` + /// Calculate inverse of a field element modulo the curve order, i.e `a^-1 % MODULUS` pub fn inverse(&self) -> Self { // Violating constant time guarantee until bug fixed in amcl if self.is_zero() { return Self::zero(); } let mut inv = self.value.clone(); - inv.invmodp(&CURVE_ORDER); + inv.invmodp(&MODULUS); inv.into() } @@ -253,7 +253,7 @@ impl FieldElement { if self.is_zero() { self.value = BigNum::new(); } else { - self.value.invmodp(&CURVE_ORDER); + self.value.invmodp(&MODULUS); } } @@ -333,9 +333,9 @@ impl FieldElement { } fn get_big_num_from_rand(r: &mut RAND) -> BigNum { - let mut n = BigNum::randomnum(&BigNum::new_big(&CURVE_ORDER), r); + let mut n = BigNum::randomnum(&BigNum::new_big(&MODULUS), r); while n.iszilch() { - n = BigNum::randomnum(&BigNum::new_big(&CURVE_ORDER), r); + n = BigNum::randomnum(&BigNum::new_big(&MODULUS), r); } n } @@ -466,14 +466,14 @@ impl FieldElement { /// Create big number from hex string in big endian pub fn from_hex(s: String) -> Result { let mut f = Self::parse_hex_as_bignum(s)?; - f.rmod(&CURVE_ORDER); + f.rmod(&MODULUS); Ok(f.into()) } /// Useful for reducing product of BigNums. Uses Barrett reduction pub fn reduce_dmod_curve_order(x: &DoubleBigNum) -> BigNum { let (k, u, v) = (*BARRETT_REDC_K, *BARRETT_REDC_U, *BARRETT_REDC_V); - barrett_reduction(&x, &CURVE_ORDER, k, &u, &v) + barrett_reduction(&x, &MODULUS, k, &u, &v) } /// Parse given hex string as BigNum in constant time. @@ -522,7 +522,7 @@ impl FieldElement { /// "sign" of x, where sgn0(x) == -1 just when x is "negative". In /// other words, this function always considers 0 to be positive. pub fn sgn0(&self) -> Sgn0 { - if self.value > *CURVE_ORDER_MINUS_1_DIV_2 { + if self.value > *MODULUS_MINUS_1_DIV_2 { Sgn0::Negative } else { Sgn0::NonNegative @@ -618,7 +618,7 @@ impl From for FieldElement { impl From<&[u8; FIELD_ELEMENT_SIZE]> for FieldElement { fn from(x: &[u8; FIELD_ELEMENT_SIZE]) -> Self { let mut n = BigNum::frombytes(x); - n.rmod(&CURVE_ORDER); + n.rmod(&MODULUS); Self { value: n } } } @@ -915,7 +915,7 @@ impl FieldElementVector { } /// Computes inner product of 2 vectors of field elements - /// [a1, a2, a3, ...field elements].[b1, b2, b3, ...field elements] = (a1*b1 + a2*b2 + a3*b3) % curve_order + /// [a1, a2, a3, ...field elements].[b1, b2, b3, ...field elements] = (a1*b1 + a2*b2 + a3*b3) % MODULUS pub fn inner_product(&self, b: &FieldElementVector) -> Result { check_vector_size_for_equality!(self, b)?; let r = (0..b.len()).into_par_iter().map(|i| (&self[i] * &b[i])).reduce(|| FieldElement::new(), |a, b| a + b); @@ -1524,11 +1524,11 @@ mod test { let mut start = Instant::now(); for i in 0..count { let mut a = l[i].clone(); - a.rmod(&CURVE_ORDER); + a.rmod(&MODULUS); let mut b = r[i].clone(); - b.rmod(&CURVE_ORDER); + b.rmod(&MODULUS); let d = BigNum::mul(&a, &b); - o1.push(barrett_reduction(&d, &CURVE_ORDER, k, &u, &v)); + o1.push(barrett_reduction(&d, &MODULUS, k, &u, &v)); } println!("Mul1 for {} elems = {:?}", count, start.elapsed()); @@ -1537,7 +1537,7 @@ mod test { let a = l[i].clone(); let b = r[i].clone(); let d = BigNum::mul(&a, &b); - o2.push(barrett_reduction(&d, &CURVE_ORDER, k, &u, &v)); + o2.push(barrett_reduction(&d, &MODULUS, k, &u, &v)); } println!("Mul2 for {} elems = {:?}", count, start.elapsed()); @@ -1548,11 +1548,11 @@ mod test { let mut x = BigNum::new_int(1isize); start = Instant::now(); for i in 0..count { - x.rmod(&CURVE_ORDER); + x.rmod(&MODULUS); let mut b = o1[i].clone(); - b.rmod(&CURVE_ORDER); + b.rmod(&MODULUS); let d = BigNum::mul(&x, &b); - x = barrett_reduction(&d, &CURVE_ORDER, k, &u, &v); + x = barrett_reduction(&d, &MODULUS, k, &u, &v); } println!("Mul1 all for {} elems = {:?}", count, start.elapsed()); @@ -1561,7 +1561,7 @@ mod test { for i in 0..count { let b = o2[i].clone(); let d = BigNum::mul(&y, &b); - y = barrett_reduction(&d, &CURVE_ORDER, k, &u, &v); + y = barrett_reduction(&d, &MODULUS, k, &u, &v); } println!("Mul2 all for {} elems = {:?}", count, start.elapsed()); @@ -1593,13 +1593,13 @@ mod test { let start = Instant::now(); for i in 0..count { - BigNum::modmul(&nums[i], &nums[i], &CURVE_ORDER); + BigNum::modmul(&nums[i], &nums[i], &MODULUS); } println!("Mul time for {} big nums = {:?}", count, start.elapsed()); let start = Instant::now(); for i in 0..count { - BigNum::modsqr(&nums[i], &CURVE_ORDER); + BigNum::modsqr(&nums[i], &MODULUS); } println!("Sqr time for {} big nums = {:?}", count, start.elapsed()); } diff --git a/src/group_elem_g1.rs b/src/group_elem_g1.rs index 29a9bb3..697c420 100644 --- a/src/group_elem_g1.rs +++ b/src/group_elem_g1.rs @@ -1,4 +1,4 @@ -use crate::constants::{CURVE_ORDER, GROUP_G1_SIZE}; +use crate::constants::{MODULUS, GROUP_G1_SIZE}; use crate::errors::{SerzDeserzError, ValueError}; use crate::field_elem::{FieldElement, FieldElementVector}; use crate::group_elem::{GroupElement, GroupElementVector}; @@ -146,7 +146,7 @@ impl GroupElement for G1 { } fn has_correct_order(&self) -> bool { - return self.value.mul(&CURVE_ORDER).is_infinity(); + return self.value.mul(&MODULUS).is_infinity(); } } diff --git a/src/group_elem_g2.rs b/src/group_elem_g2.rs index 27dc688..5aa68df 100644 --- a/src/group_elem_g2.rs +++ b/src/group_elem_g2.rs @@ -1,4 +1,4 @@ -use crate::constants::{CURVE_ORDER, GROUP_G2_SIZE}; +use crate::constants::{MODULUS, GROUP_G2_SIZE}; use crate::errors::{SerzDeserzError, ValueError}; use crate::field_elem::{FieldElement, FieldElementVector}; use crate::group_elem::{GroupElement, GroupElementVector}; @@ -148,7 +148,7 @@ impl GroupElement for G2 { } fn has_correct_order(&self) -> bool { - return self.value.mul(&CURVE_ORDER).is_infinity(); + return self.value.mul(&MODULUS).is_infinity(); } } diff --git a/src/utils.rs b/src/utils.rs index 57b681a..a9b1f63 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -3,7 +3,7 @@ extern crate sha3; use rand::{CryptoRng, RngCore}; -use crate::constants::{CURVE_ORDER, FIELD_ELEMENT_SIZE}; +use crate::constants::{MODULUS, FIELD_ELEMENT_SIZE}; use crate::types::{BigNum, DoubleBigNum}; use amcl::rand::RAND; @@ -140,14 +140,14 @@ fn __barrett_reduction__(x: &BigNum, modulus: &BigNum, k: usize, u: &BigNum, v: pub fn barrett_reduction_params(modulus: &BigNum) -> (usize, BigNum, BigNum) { let k = modulus.nbits(); - // u = floor(2^2k/CURVE_ORDER) + // u = floor(2^2k/MODULUS) let mut u = DoubleBigNum::new(); u.w[0] = 1; // `u.shl(2*k)` crashes, so perform shl(k) twice u.shl(k); u.shl(k); // div returns floored value - let u = u.div(&CURVE_ORDER); + let u = u.div(&MODULUS); // v = 2^(k+1) let mut v = BigNum::new_int(1isize); @@ -179,7 +179,7 @@ mod test { let mut res_mul = BIG::new_int(1 as isize); let mut start = Instant::now(); for b in &bigs { - res_mul = BigNum::modmul(&res_mul, &b, &CURVE_ORDER); + res_mul = BigNum::modmul(&res_mul, &b, &MODULUS); } println!( "Multiplication time for {} BIGs = {:?}", @@ -215,12 +215,12 @@ mod test { start = Instant::now(); for b in &bigs { let mut i = b.clone(); - i.invmodp(&CURVE_ORDER); + i.invmodp(&MODULUS); inverses_b.push(i); } println!("Inverse time for {} BIGs = {:?}", count, start.elapsed()); for i in 0..count { - let r = BigNum::modmul(&inverses_b[i], &bigs[i], &CURVE_ORDER); + let r = BigNum::modmul(&inverses_b[i], &bigs[i], &MODULUS); assert_eq!(BigNum::comp(&r, &BigNum::new_int(1 as isize)), 0); } @@ -243,7 +243,7 @@ mod test { let mut r = bigs[0]; for i in 0..c { r.add(&bigs[i]); - r.rmod(&CURVE_ORDER); + r.rmod(&MODULUS); } println!("Addition time for {} BIGs = {:?}", c, start.elapsed()); @@ -296,7 +296,7 @@ mod test { #[test] fn timing_barrett_reduction() { - //let (k, u, v) = barrett_reduction_params(&CURVE_ORDER); + //let (k, u, v) = barrett_reduction_params(&MODULUS); let (k, u, v) = ( *constants::BARRETT_REDC_K, *constants::BARRETT_REDC_U, @@ -310,13 +310,13 @@ mod test { for _ in 0..count { let a: u32 = rng.gen(); let s = BigNum::new_int(a as isize); - let _x = CURVE_ORDER.minus(&s); + let _x = MODULUS.minus(&s); xs.push(BigNum::mul(&_x, &_x)); } let mut start = Instant::now(); for x in &xs { - let r = barrett_reduction(&x, &CURVE_ORDER, k, &u, &v); + let r = barrett_reduction(&x, &MODULUS, k, &u, &v); reduced1.push(r); } println!("Barrett time = {:?}", start.elapsed()); @@ -324,7 +324,7 @@ mod test { start = Instant::now(); for x in &xs { let mut y = x.clone(); - let z = y.dmod(&CURVE_ORDER); + let z = y.dmod(&MODULUS); reduced2.push(z); } println!("Normal time = {:?}", start.elapsed()); @@ -349,7 +349,7 @@ mod test { let mut start = Instant::now(); for i in 0..count { sum = BigNum::plus(&sum, &bigs[i]); - sum.rmod(&CURVE_ORDER) + sum.rmod(&MODULUS) } println!("rmod time = {:?}", start.elapsed()); @@ -357,7 +357,7 @@ mod test { start = Instant::now(); for i in 0..count { sum_b = BigNum::plus(&sum_b, &bigs[i]); - sum_b = __barrett_reduction__(&sum_b, &CURVE_ORDER, k, &u, &v) + sum_b = __barrett_reduction__(&sum_b, &MODULUS, k, &u, &v) } println!("Barrett time = {:?}", start.elapsed()); From 075c5756e1f545146cd2e73c2190e320ea025a03 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Mon, 23 Mar 2020 13:29:02 -0600 Subject: [PATCH 07/15] Fix minor tests Signed-off-by: Michael Lodder --- src/extension_field_gt.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/extension_field_gt.rs b/src/extension_field_gt.rs index 1380085..563586b 100644 --- a/src/extension_field_gt.rs +++ b/src/extension_field_gt.rs @@ -293,7 +293,7 @@ mod test { >::ate_pairing(&g1, &g2), >::ate_pairing(&g1_identity, &g2), ); - assert!(lhs == rhs); + assert_eq!(lhs, rhs); // e(g1, g2 + identity) == e(g1, g2)*e(g1, identity) let lhs = GT::ate_pairing(&g1, &(&g2 + &g2_identity)); @@ -301,7 +301,7 @@ mod test { >::ate_pairing(&g1, &g2), >::ate_pairing(&g1, &g2_identity), ); - assert!(lhs == rhs); + assert_eq!(lhs, rhs); let h1 = G1::random(); let h2 = G2::random(); @@ -312,7 +312,7 @@ mod test { >::ate_pairing(&g1_identity, &h2), ); let rhs = GT::ate_pairing(&g1, &g2); - assert!(lhs == rhs); + assert_eq!(lhs, rhs); // e(identity, g2)*e(h1, h2) == e(h1, h2) let lhs = GT::product( @@ -320,15 +320,15 @@ mod test { >::ate_pairing(&h1, &h2), ); let rhs = GT::ate_pairing(&h1, &h2); - assert!(lhs == rhs); + assert_eq!(lhs, rhs); assert!(GT::ate_pairing(&g1_identity, &g2_identity).is_one()); // 2-pairing - assert!(GT::ate_2_pairing(&g1, &g2, &g1_identity, &h2) == GT::ate_pairing(&g1, &g2)); - assert!(GT::ate_2_pairing(&g1, &g2, &h1, &g2_identity) == GT::ate_pairing(&g1, &g2)); - assert!(GT::ate_2_pairing(&g1_identity, &g2, &h1, &h2) == GT::ate_pairing(&h1, &h2)); - assert!(GT::ate_2_pairing(&g1, &g2_identity, &h1, &h2) == GT::ate_pairing(&h1, &h2)); + assert_eq!(GT::ate_2_pairing(&g1, &g2, &g1_identity, &h2), GT::ate_pairing(&g1, &g2)); + assert_eq!(GT::ate_2_pairing(&g1, &g2, &h1, &g2_identity), GT::ate_pairing(&g1, &g2)); + assert_eq!(GT::ate_2_pairing(&g1_identity, &g2, &h1, &h2), GT::ate_pairing(&h1, &h2)); + assert_eq!(GT::ate_2_pairing(&g1, &g2_identity, &h1, &h2), GT::ate_pairing(&h1, &h2)); assert!(GT::ate_2_pairing(&g1_identity, &g2_identity, &g1_identity, &g2_identity).is_one()); let k1 = G1::random(); @@ -373,20 +373,20 @@ mod test { // e(g1, -g2) == e(-g1, g2) let lhs = GT::ate_pairing(&g1, &g2_neg); let rhs = GT::ate_pairing(&g1_neg, &g2); - assert!(lhs == rhs); + assert_eq!(lhs, rhs); // e(g1, -g2) == e(-g1, g2) == e(g1, g2)^-1 let e = GT::ate_pairing(&g1, &g2); let e_inv = e.inverse(); - assert!(lhs == e_inv); + assert_eq!(lhs, e_inv); let p = GT::ate_pairing(&g1, &g2); // e(g1, g2) = e(-g1, g2)^-1 => e(g1, g2) * e(-g1, g2) == 1 - assert!(GT::product(&p, &lhs) == GT::one()); + assert_eq!(GT::product(&p, &lhs), GT::one()); // e(g1, g2) = e(g1, -g2)^-1 => e(g1, g2) * e(g1, -g2) == 1 - assert!(GT::product(&p, &rhs) == GT::one()); + assert_eq!(GT::product(&p, &rhs), GT::one()); } #[test] @@ -477,10 +477,10 @@ mod test { count, start.elapsed() ); - assert!(accum == multi); + assert_eq!(accum, multi); let ip = GT::inner_product(&g1_vec, &g2_vec).unwrap(); - assert!(accum == ip); + assert_eq!(accum, ip); } #[test] From 1a71ea596034d535ceb8db1ef46619edfbaef511 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Mon, 23 Mar 2020 15:44:07 -0600 Subject: [PATCH 08/15] Make MODULUS const Signed-off-by: Michael Lodder --- src/constants.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 82124f0..b5c280a 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -13,13 +13,14 @@ pub const FIELD_ELEMENT_SIZE: usize = MODBYTES; // Byte size of element in group G1, 1 extra byte for compression flag pub const GROUP_G1_SIZE: usize = (2 * MODBYTES + 1) as usize; +pub const MODULUS: BigNum = BigNum{ w: rom::MODULUS }; + lazy_static! { pub static ref GENERATOR_G1: GroupG1 = GroupG1::generator(); - pub static ref MODULUS: BigNum = BigNum::new_ints(&rom::MODULUS); pub static ref MODULUS_BITS: usize = MODULUS.nbits(); pub static ref CURVE_ORDER: BigNum = BigNum::new_ints(&rom::CURVE_ORDER); pub static ref MODULUS_MINUS_1_DIV_2: BigNum = { - let mut order = BigNum::new_ints(&rom::MODULUS); + let mut order = MODULUS; order.dec(1); order.shr(1); order @@ -49,3 +50,4 @@ lazy_static! { #[cfg(any(feature = "bls381", feature = "bn254"))] pub use crate::types_g2::{GENERATOR_G2, GROUP_G2_SIZE, GROUP_GT_SIZE}; + From 2410444c1c1abeeccda234e8cbca456a5f9636f6 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Mon, 23 Mar 2020 15:48:01 -0600 Subject: [PATCH 09/15] More constants Signed-off-by: Michael Lodder --- src/constants.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index b5c280a..925f53e 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -13,12 +13,13 @@ pub const FIELD_ELEMENT_SIZE: usize = MODBYTES; // Byte size of element in group G1, 1 extra byte for compression flag pub const GROUP_G1_SIZE: usize = (2 * MODBYTES + 1) as usize; -pub const MODULUS: BigNum = BigNum{ w: rom::MODULUS }; +pub const MODULUS: BigNum = BigNum { w: rom::MODULUS }; +pub const CURVE_ORDER: BigNum = BigNum { w: rom::CURVE_ORDER }; +pub const FIELD_ELEMENT_ZERO: BigNum = BigNum { w: [0; NLEN] }; lazy_static! { pub static ref GENERATOR_G1: GroupG1 = GroupG1::generator(); pub static ref MODULUS_BITS: usize = MODULUS.nbits(); - pub static ref CURVE_ORDER: BigNum = BigNum::new_ints(&rom::CURVE_ORDER); pub static ref MODULUS_MINUS_1_DIV_2: BigNum = { let mut order = MODULUS; order.dec(1); @@ -26,7 +27,6 @@ lazy_static! { order }; pub static ref CURVE_ORDER_BIT_SIZE: usize = CURVE_ORDER.nbits(); - pub static ref FIELD_ELEMENT_ZERO: BigNum = BigNum::new(); pub static ref BARRETT_REDC_K: usize = MODULUS.nbits(); pub static ref BARRETT_REDC_U: BigNum = { let k = MODULUS.nbits(); From 94378e38c74ee7847306197c9a3499264004607e Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Wed, 25 Mar 2020 07:39:42 -0600 Subject: [PATCH 10/15] Add calls to hash2curve Signed-off-by: Michael Lodder --- Cargo.toml | 4 ++++ src/group_elem.rs | 4 ++++ src/group_elem_g1.rs | 19 +++++++++++++++++++ src/group_elem_g2.rs | 5 +++++ 4 files changed, 32 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index e1ca2c9..0b7ad61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,10 @@ sha3 = "0.8.2" rayon = "1.3" subtle-encoding = "0.5.0" +[dependencies.hash2curve] +version = "0.0.1" +features = ["bls"] + [dependencies.amcl] package = "miracl_amcl" version = "3.2.5" diff --git a/src/group_elem.rs b/src/group_elem.rs index d58ba61..999d7b8 100644 --- a/src/group_elem.rs +++ b/src/group_elem.rs @@ -46,8 +46,12 @@ pub trait GroupElement: Clone + Sized { fn set_to_identity(&mut self); /// Hash an arbitrary sized message using SHAKE and return output as group element + #[deprecated(since = "0.4.0", note = "Please use `hash_to_curve` instead")] fn from_msg_hash(msg: &[u8]) -> Self; + /// Uses IETF constant time hash_to_curve method to map data to a point + fn hash_to_curve(msg: &[u8], dst: &hash2curve::DomainSeparationTag) -> Self; + /// Return byte representation as vector fn to_bytes(&self) -> Vec; diff --git a/src/group_elem_g1.rs b/src/group_elem_g1.rs index 697c420..c1a640a 100644 --- a/src/group_elem_g1.rs +++ b/src/group_elem_g1.rs @@ -16,6 +16,7 @@ use serde::de::{Deserialize, Deserializer, Error as DError, Visitor}; use serde::ser::{Serialize, Serializer}; use std::str::{FromStr, SplitWhitespace}; use zeroize::Zeroize; +use hash2curve::HashToCurveXmd; #[derive(Clone, Debug)] pub struct G1 { @@ -52,6 +53,14 @@ impl GroupElement for G1 { GroupG1::mapit(&hash_msg(msg)).into() } + fn hash_to_curve(msg: &[u8], dst: &hash2curve::DomainSeparationTag) -> Self { + let hasher = hash2curve::bls381g1::Bls12381G1Sswu::new(dst.clone()); + match hasher.hash_to_curve_xmd::(msg) { + Ok(p) => p.into(), + Err(_) => Self::identity() + } + } + fn to_bytes(&self) -> Vec { let mut bytes: [u8; GROUP_G1_SIZE] = [0; GROUP_G1_SIZE]; self.write_to_slice_unchecked(&mut bytes); @@ -214,6 +223,16 @@ pub fn parse_hex_as_fp(iter: &mut SplitWhitespace) -> Result Self { + unimplemented!(); + } + fn to_bytes(&self) -> Vec { let mut bytes: [u8; GROUP_G2_SIZE] = [0; GROUP_G2_SIZE]; self.write_to_slice_unchecked(&mut bytes); From dfd94ae2fe329246dd6a013efb88495ca94d2293 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Mon, 20 Apr 2020 08:11:30 -0600 Subject: [PATCH 11/15] Revert "Change to use reduction via modulus" This reverts commit 9ca2b2a17456769b3116d3a40828e6b4520ec995. Signed-off-by: Michael Lodder --- src/constants.rs | 6 ++-- src/field_elem.rs | 68 ++++++++++++++++++++++---------------------- src/group_elem_g1.rs | 4 +-- src/group_elem_g2.rs | 4 +-- src/utils.rs | 26 ++++++++--------- 5 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 925f53e..7bb6f0c 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -29,7 +29,7 @@ lazy_static! { pub static ref CURVE_ORDER_BIT_SIZE: usize = CURVE_ORDER.nbits(); pub static ref BARRETT_REDC_K: usize = MODULUS.nbits(); pub static ref BARRETT_REDC_U: BigNum = { - let k = MODULUS.nbits(); + let k = CURVE_ORDER.nbits(); let mut u = DoubleBigNum::new(); u.w[0] = 1; // `u.shl(2*k)` crashes, so perform shl(k) twice @@ -37,11 +37,11 @@ lazy_static! { u.shl(k); // div returns floored value - u.div(&MODULUS) + u.div(&CURVE_ORDER) }; pub static ref BARRETT_REDC_V: BigNum = { - let k = MODULUS.nbits(); + let k = CURVE_ORDER.nbits(); let mut v = BigNum::new_int(1isize); v.shl(k+1); v diff --git a/src/field_elem.rs b/src/field_elem.rs index a9bd2e2..3f5f34f 100644 --- a/src/field_elem.rs +++ b/src/field_elem.rs @@ -1,8 +1,8 @@ use rand::{CryptoRng, RngCore}; use crate::constants::{ - BARRETT_REDC_K, BARRETT_REDC_U, BARRETT_REDC_V, BIG_NUM_BITS, MODULUS, FIELD_ELEMENT_SIZE, NLEN, - MODULUS_MINUS_1_DIV_2 + BARRETT_REDC_K, BARRETT_REDC_U, BARRETT_REDC_V, BIG_NUM_BITS, CURVE_ORDER, FIELD_ELEMENT_SIZE, NLEN, + CURVE_ORDER_MINUS_1_DIV_2 }; use crate::errors::{SerzDeserzError, ValueError}; use crate::signum::Sgn0; @@ -133,7 +133,7 @@ impl FieldElement { )); } let mut n = BigNum::frombytes(bytes); - n.rmod(&MODULUS); + n.rmod(&CURVE_ORDER); Ok(Self { value: n }) } @@ -159,7 +159,7 @@ impl FieldElement { pub fn to_bignum(&self) -> BigNum { let mut v = self.value.clone(); - v.rmod(&MODULUS); + v.rmod(&CURVE_ORDER); v } @@ -178,51 +178,51 @@ impl FieldElement { pub fn add_assign_(&mut self, b: &Self) { // Not using `self.plus` to avoid cloning. Breaking the abstraction a bit for performance. self.value.add(&b.value); - self.value.rmod(&MODULUS); + self.value.rmod(&CURVE_ORDER); } /// Subtract a field element from itself. `self = self - b` pub fn sub_assign_(&mut self, b: &Self) { // Not using `self.minus` to avoid cloning. Breaking the abstraction a bit for performance. - let neg_b = BigNum::modneg(&b.value, &MODULUS); + let neg_b = BigNum::modneg(&b.value, &CURVE_ORDER); self.value.add(&neg_b); - self.value.rmod(&MODULUS); + self.value.rmod(&CURVE_ORDER); } /// Return sum of a field element and itself. `self + b` pub fn plus(&self, b: &Self) -> Self { let mut sum = self.value.clone(); sum.add(&b.value); - sum.rmod(&MODULUS); + sum.rmod(&CURVE_ORDER); sum.into() } /// Return difference of a field element and itself. `self - b` pub fn minus(&self, b: &Self) -> Self { let mut sum = self.value.clone(); - let neg_b = BigNum::modneg(&b.value, &MODULUS); + let neg_b = BigNum::modneg(&b.value, &CURVE_ORDER); sum.add(&neg_b); - sum.rmod(&MODULUS); + sum.rmod(&CURVE_ORDER); sum.into() } /// Multiply 2 field elements modulus the order of the curve. - /// (field_element_a * field_element_b) % modulus + /// (field_element_a * field_element_b) % curve_order pub fn multiply(&self, b: &Self) -> Self { let d = BigNum::mul(&self.value, &b.value); Self::reduce_dmod_curve_order(&d).into() } - /// Calculate square of a field element modulo the curve order, i.e `a^2 % MODULUS` + /// Calculate square of a field element modulo the curve order, i.e `a^2 % curve_order` pub fn square(&self) -> Self { let d = BigNum::sqr(&self.value); Self::reduce_dmod_curve_order(&d).into() } - /// Exponentiation modulo curve order, i.e. self^exp % MODULUS + /// Exponentiation modulo curve order, i.e. self^exp % CURVE_ORDER pub fn pow(&self, exp: &Self) -> Self { let mut base = self.value.clone(); - let res = base.powmod(&exp.value, &MODULUS); + let res = base.powmod(&exp.value, &CURVE_ORDER); res.into() } @@ -237,14 +237,14 @@ impl FieldElement { self.value = zero.minus(&self).value; } - /// Calculate inverse of a field element modulo the curve order, i.e `a^-1 % MODULUS` + /// Calculate inverse of a field element modulo the curve order, i.e `a^-1 % curve_order` pub fn inverse(&self) -> Self { // Violating constant time guarantee until bug fixed in amcl if self.is_zero() { return Self::zero(); } let mut inv = self.value.clone(); - inv.invmodp(&MODULUS); + inv.invmodp(&CURVE_ORDER); inv.into() } @@ -253,7 +253,7 @@ impl FieldElement { if self.is_zero() { self.value = BigNum::new(); } else { - self.value.invmodp(&MODULUS); + self.value.invmodp(&CURVE_ORDER); } } @@ -333,9 +333,9 @@ impl FieldElement { } fn get_big_num_from_rand(r: &mut RAND) -> BigNum { - let mut n = BigNum::randomnum(&BigNum::new_big(&MODULUS), r); + let mut n = BigNum::randomnum(&BigNum::new_big(&CURVE_ORDER), r); while n.iszilch() { - n = BigNum::randomnum(&BigNum::new_big(&MODULUS), r); + n = BigNum::randomnum(&BigNum::new_big(&CURVE_ORDER), r); } n } @@ -466,14 +466,14 @@ impl FieldElement { /// Create big number from hex string in big endian pub fn from_hex(s: String) -> Result { let mut f = Self::parse_hex_as_bignum(s)?; - f.rmod(&MODULUS); + f.rmod(&CURVE_ORDER); Ok(f.into()) } /// Useful for reducing product of BigNums. Uses Barrett reduction pub fn reduce_dmod_curve_order(x: &DoubleBigNum) -> BigNum { let (k, u, v) = (*BARRETT_REDC_K, *BARRETT_REDC_U, *BARRETT_REDC_V); - barrett_reduction(&x, &MODULUS, k, &u, &v) + barrett_reduction(&x, &CURVE_ORDER, k, &u, &v) } /// Parse given hex string as BigNum in constant time. @@ -522,7 +522,7 @@ impl FieldElement { /// "sign" of x, where sgn0(x) == -1 just when x is "negative". In /// other words, this function always considers 0 to be positive. pub fn sgn0(&self) -> Sgn0 { - if self.value > *MODULUS_MINUS_1_DIV_2 { + if self.value > *CURVE_ORDER_MINUS_1_DIV_2 { Sgn0::Negative } else { Sgn0::NonNegative @@ -618,7 +618,7 @@ impl From for FieldElement { impl From<&[u8; FIELD_ELEMENT_SIZE]> for FieldElement { fn from(x: &[u8; FIELD_ELEMENT_SIZE]) -> Self { let mut n = BigNum::frombytes(x); - n.rmod(&MODULUS); + n.rmod(&CURVE_ORDER); Self { value: n } } } @@ -915,7 +915,7 @@ impl FieldElementVector { } /// Computes inner product of 2 vectors of field elements - /// [a1, a2, a3, ...field elements].[b1, b2, b3, ...field elements] = (a1*b1 + a2*b2 + a3*b3) % MODULUS + /// [a1, a2, a3, ...field elements].[b1, b2, b3, ...field elements] = (a1*b1 + a2*b2 + a3*b3) % curve_order pub fn inner_product(&self, b: &FieldElementVector) -> Result { check_vector_size_for_equality!(self, b)?; let r = (0..b.len()).into_par_iter().map(|i| (&self[i] * &b[i])).reduce(|| FieldElement::new(), |a, b| a + b); @@ -1524,11 +1524,11 @@ mod test { let mut start = Instant::now(); for i in 0..count { let mut a = l[i].clone(); - a.rmod(&MODULUS); + a.rmod(&CURVE_ORDER); let mut b = r[i].clone(); - b.rmod(&MODULUS); + b.rmod(&CURVE_ORDER); let d = BigNum::mul(&a, &b); - o1.push(barrett_reduction(&d, &MODULUS, k, &u, &v)); + o1.push(barrett_reduction(&d, &CURVE_ORDER, k, &u, &v)); } println!("Mul1 for {} elems = {:?}", count, start.elapsed()); @@ -1537,7 +1537,7 @@ mod test { let a = l[i].clone(); let b = r[i].clone(); let d = BigNum::mul(&a, &b); - o2.push(barrett_reduction(&d, &MODULUS, k, &u, &v)); + o2.push(barrett_reduction(&d, &CURVE_ORDER, k, &u, &v)); } println!("Mul2 for {} elems = {:?}", count, start.elapsed()); @@ -1548,11 +1548,11 @@ mod test { let mut x = BigNum::new_int(1isize); start = Instant::now(); for i in 0..count { - x.rmod(&MODULUS); + x.rmod(&CURVE_ORDER); let mut b = o1[i].clone(); - b.rmod(&MODULUS); + b.rmod(&CURVE_ORDER); let d = BigNum::mul(&x, &b); - x = barrett_reduction(&d, &MODULUS, k, &u, &v); + x = barrett_reduction(&d, &CURVE_ORDER, k, &u, &v); } println!("Mul1 all for {} elems = {:?}", count, start.elapsed()); @@ -1561,7 +1561,7 @@ mod test { for i in 0..count { let b = o2[i].clone(); let d = BigNum::mul(&y, &b); - y = barrett_reduction(&d, &MODULUS, k, &u, &v); + y = barrett_reduction(&d, &CURVE_ORDER, k, &u, &v); } println!("Mul2 all for {} elems = {:?}", count, start.elapsed()); @@ -1593,13 +1593,13 @@ mod test { let start = Instant::now(); for i in 0..count { - BigNum::modmul(&nums[i], &nums[i], &MODULUS); + BigNum::modmul(&nums[i], &nums[i], &CURVE_ORDER); } println!("Mul time for {} big nums = {:?}", count, start.elapsed()); let start = Instant::now(); for i in 0..count { - BigNum::modsqr(&nums[i], &MODULUS); + BigNum::modsqr(&nums[i], &CURVE_ORDER); } println!("Sqr time for {} big nums = {:?}", count, start.elapsed()); } diff --git a/src/group_elem_g1.rs b/src/group_elem_g1.rs index c1a640a..2c8ef28 100644 --- a/src/group_elem_g1.rs +++ b/src/group_elem_g1.rs @@ -1,4 +1,4 @@ -use crate::constants::{MODULUS, GROUP_G1_SIZE}; +use crate::constants::{CURVE_ORDER, GROUP_G1_SIZE}; use crate::errors::{SerzDeserzError, ValueError}; use crate::field_elem::{FieldElement, FieldElementVector}; use crate::group_elem::{GroupElement, GroupElementVector}; @@ -155,7 +155,7 @@ impl GroupElement for G1 { } fn has_correct_order(&self) -> bool { - return self.value.mul(&MODULUS).is_infinity(); + return self.value.mul(&CURVE_ORDER).is_infinity(); } } diff --git a/src/group_elem_g2.rs b/src/group_elem_g2.rs index 823d823..ef95a5a 100644 --- a/src/group_elem_g2.rs +++ b/src/group_elem_g2.rs @@ -1,4 +1,4 @@ -use crate::constants::{MODULUS, GROUP_G2_SIZE}; +use crate::constants::{CURVE_ORDER, GROUP_G2_SIZE}; use crate::errors::{SerzDeserzError, ValueError}; use crate::field_elem::{FieldElement, FieldElementVector}; use crate::group_elem::{GroupElement, GroupElementVector}; @@ -153,7 +153,7 @@ impl GroupElement for G2 { } fn has_correct_order(&self) -> bool { - return self.value.mul(&MODULUS).is_infinity(); + return self.value.mul(&CURVE_ORDER).is_infinity(); } } diff --git a/src/utils.rs b/src/utils.rs index a9b1f63..57b681a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -3,7 +3,7 @@ extern crate sha3; use rand::{CryptoRng, RngCore}; -use crate::constants::{MODULUS, FIELD_ELEMENT_SIZE}; +use crate::constants::{CURVE_ORDER, FIELD_ELEMENT_SIZE}; use crate::types::{BigNum, DoubleBigNum}; use amcl::rand::RAND; @@ -140,14 +140,14 @@ fn __barrett_reduction__(x: &BigNum, modulus: &BigNum, k: usize, u: &BigNum, v: pub fn barrett_reduction_params(modulus: &BigNum) -> (usize, BigNum, BigNum) { let k = modulus.nbits(); - // u = floor(2^2k/MODULUS) + // u = floor(2^2k/CURVE_ORDER) let mut u = DoubleBigNum::new(); u.w[0] = 1; // `u.shl(2*k)` crashes, so perform shl(k) twice u.shl(k); u.shl(k); // div returns floored value - let u = u.div(&MODULUS); + let u = u.div(&CURVE_ORDER); // v = 2^(k+1) let mut v = BigNum::new_int(1isize); @@ -179,7 +179,7 @@ mod test { let mut res_mul = BIG::new_int(1 as isize); let mut start = Instant::now(); for b in &bigs { - res_mul = BigNum::modmul(&res_mul, &b, &MODULUS); + res_mul = BigNum::modmul(&res_mul, &b, &CURVE_ORDER); } println!( "Multiplication time for {} BIGs = {:?}", @@ -215,12 +215,12 @@ mod test { start = Instant::now(); for b in &bigs { let mut i = b.clone(); - i.invmodp(&MODULUS); + i.invmodp(&CURVE_ORDER); inverses_b.push(i); } println!("Inverse time for {} BIGs = {:?}", count, start.elapsed()); for i in 0..count { - let r = BigNum::modmul(&inverses_b[i], &bigs[i], &MODULUS); + let r = BigNum::modmul(&inverses_b[i], &bigs[i], &CURVE_ORDER); assert_eq!(BigNum::comp(&r, &BigNum::new_int(1 as isize)), 0); } @@ -243,7 +243,7 @@ mod test { let mut r = bigs[0]; for i in 0..c { r.add(&bigs[i]); - r.rmod(&MODULUS); + r.rmod(&CURVE_ORDER); } println!("Addition time for {} BIGs = {:?}", c, start.elapsed()); @@ -296,7 +296,7 @@ mod test { #[test] fn timing_barrett_reduction() { - //let (k, u, v) = barrett_reduction_params(&MODULUS); + //let (k, u, v) = barrett_reduction_params(&CURVE_ORDER); let (k, u, v) = ( *constants::BARRETT_REDC_K, *constants::BARRETT_REDC_U, @@ -310,13 +310,13 @@ mod test { for _ in 0..count { let a: u32 = rng.gen(); let s = BigNum::new_int(a as isize); - let _x = MODULUS.minus(&s); + let _x = CURVE_ORDER.minus(&s); xs.push(BigNum::mul(&_x, &_x)); } let mut start = Instant::now(); for x in &xs { - let r = barrett_reduction(&x, &MODULUS, k, &u, &v); + let r = barrett_reduction(&x, &CURVE_ORDER, k, &u, &v); reduced1.push(r); } println!("Barrett time = {:?}", start.elapsed()); @@ -324,7 +324,7 @@ mod test { start = Instant::now(); for x in &xs { let mut y = x.clone(); - let z = y.dmod(&MODULUS); + let z = y.dmod(&CURVE_ORDER); reduced2.push(z); } println!("Normal time = {:?}", start.elapsed()); @@ -349,7 +349,7 @@ mod test { let mut start = Instant::now(); for i in 0..count { sum = BigNum::plus(&sum, &bigs[i]); - sum.rmod(&MODULUS) + sum.rmod(&CURVE_ORDER) } println!("rmod time = {:?}", start.elapsed()); @@ -357,7 +357,7 @@ mod test { start = Instant::now(); for i in 0..count { sum_b = BigNum::plus(&sum_b, &bigs[i]); - sum_b = __barrett_reduction__(&sum_b, &MODULUS, k, &u, &v) + sum_b = __barrett_reduction__(&sum_b, &CURVE_ORDER, k, &u, &v) } println!("Barrett time = {:?}", start.elapsed()); From 06683b8e27fb386e5cde7826112e8767362c5e5c Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Tue, 21 Apr 2020 14:16:07 -0600 Subject: [PATCH 12/15] Update to 0.5.0 Signed-off-by: Michael Lodder --- Cargo.toml | 30 +- README.md | 10 +- src/commitment.rs | 12 +- src/constants.rs | 18 +- src/{field_elem.rs => curve_order_elem.rs} | 911 +++++++++++---------- src/extension_field_gt.rs | 16 +- src/group_elem.rs | 106 +-- src/group_elem_g1.rs | 105 ++- src/group_elem_g2.rs | 100 ++- src/lib.rs | 16 +- src/signum.rs | 22 - src/univar_poly.rs | 430 +++++----- src/utils.rs | 18 +- 13 files changed, 955 insertions(+), 839 deletions(-) rename src/{field_elem.rs => curve_order_elem.rs} (57%) delete mode 100644 src/signum.rs diff --git a/Cargo.toml b/Cargo.toml index 0b7ad61..b3961e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [package] -name = "amcl_wrapper" -version = "0.4.0" +name = "amcl_wrapper_ml" +version = "0.5.0" authors = ["lovesh harchandani ", "Michael Lodder "] description = "Wapper over Milagro Cryptographic Library (version 3)" -repository = "https://github.com/lovesh/amcl_rust_wrapper" +repository = "https://github.com/mikelodder7/amcl_rust_wrapper" license = "Apache-2.0" edition = "2018" @@ -20,24 +20,24 @@ secp256k1 = [] ed25519 = [] [dependencies] +arrayref = "0.3" +byteorder = "1.3" +lazy_static = "1.3" rand = "0.7" -lazy_static = "1.3.0" -byteorder = "1.3.1" -serde = "1.0" -serde_json = "1.0" -serde_derive = "1.0" -zeroize = "1.1.0" -#tiny-keccak = "1.5" -sha3 = "0.8.2" rayon = "1.3" -subtle-encoding = "0.5.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +sha2 = "0.8" +sha3 = "0.8" +subtle-encoding = "0.5" +zeroize = "1.1" [dependencies.hash2curve] -version = "0.0.1" +version = "0.0.6" features = ["bls"] [dependencies.amcl] -package = "miracl_amcl" -version = "3.2.5" +package = "amcl-milagro" +version = "3.2.6" features = ["bls381", "bn254", "secp256k1", "ed25519"] diff --git a/README.md b/README.md index 6d4b62b..4c7b1c6 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ let b = G1::from_msg_hash(msg.as_bytes()); 4. Create vectors of field elements and do some operations ```rust // creates a vector of size 10 with all elements as 0 -let mut a = FieldElementVector::new(10); +let mut a = CurveOrderElementVector::new(10); // Add 2 more elements to the above vector a.push(FieldElement::random()); a.push(FieldElement::random()); @@ -154,7 +154,7 @@ a.sum(); // sum of elements of vector ```rust // Return a Vandermonde vector of a given field element, i.e. given element `k` and size `n`, return vector as `vec![1, k, k^2, k^3, ... k^n-1]` let k = FieldElement::random(); -let van_vec = FieldElementVector::new_vandermonde_vector(&k, 5); +let van_vec = CurveOrderElementVector::new_vandermonde_vector(&k, 5); ``` ```rust @@ -162,7 +162,7 @@ let van_vec = FieldElementVector::new_vandermonde_vector(&k, 5); let rands: Vec<_> = (0..10).map(|_| FieldElement::random()).collect(); // an alternative way of creating vector of size 10 of random field elements -let rands_1 = FieldElementVector::random(10); +let rands_1 = CurveOrderElementVector::random(10); ``` ```rust @@ -209,7 +209,7 @@ let diff_vec = rands.minus(&rands_1); // eg. given a vector of group elements and field elements, G and F respectively, compute G[0]*F[0] + G[1]*F[1] + G[2]*F[2] + .. G[n-1]*F[n-1] // requires vectors to be of same length let g = G1Vector::random(10); -let f = FieldElementVector::random(10); +let f = CurveOrderElementVector::random(10); // Uses constant time multi-scalar multiplication `multi_scalar_mul_const_time` underneath. let ip = g.inner_product_const_time(&f); @@ -267,7 +267,7 @@ assert!(poly.is_zero()); // Create a polynomial from field elements as coefficients, the following polynomial will be c_0 + c_1*x + c_2*x^2 + c_3*x^3 + ... + c_d*x^d let coeffs: Vec = vec![c_0, c_1, ... coefficients for smaller to higher degrees ..., c_d]; -let poly1 = UnivarPolynomial(FieldElementVector::from(coeffs)); +let poly1 = UnivarPolynomial(CurveOrderElementVector::from(coeffs)); // Create a polynomial of degree `d` with random coefficients let poly2 = UnivarPolynomial::random(d); diff --git a/src/commitment.rs b/src/commitment.rs index 9675a99..b19b756 100644 --- a/src/commitment.rs +++ b/src/commitment.rs @@ -1,10 +1,10 @@ use crate::errors::ValueError; -use crate::field_elem::{FieldElement, FieldElementVector}; +use crate::curve_order_elem::{CurveOrderElement, CurveOrderElementVector}; use crate::group_elem::GroupElementVector; use crate::group_elem_g1::{G1Vector, G1}; /// Commit to field element `elem` with randomness `r` given groups elements `g` and `h`, i.e. compute g^elem.h^r -pub fn commit_to_field_element(g: &G1, h: &G1, elem: &FieldElement, r: &FieldElement) -> G1 { +pub fn commit_to_field_element(g: &G1, h: &G1, elem: &CurveOrderElement, r: &CurveOrderElement) -> G1 { g.binary_scalar_mul(h, elem, r) } @@ -15,9 +15,9 @@ pub fn commit_to_field_element_vectors( g: &G1Vector, h: &G1Vector, u: &G1, - a: &FieldElementVector, - b: &FieldElementVector, - c: &FieldElement, + a: &CurveOrderElementVector, + b: &CurveOrderElementVector, + c: &CurveOrderElement, ) -> Result { /*let a_g = g.inner_product_const_time(a)?; let b_h = h.inner_product_const_time(b)?; @@ -28,7 +28,7 @@ pub fn commit_to_field_element_vectors( combined_g.extend_from_slice(h.as_slice()); combined_g.push(u.clone()); - let mut combined_f: Vec = vec![]; + let mut combined_f: Vec = vec![]; combined_f.extend_from_slice(a.as_slice()); combined_f.extend_from_slice(b.as_slice()); combined_f.push(c.clone()); diff --git a/src/constants.rs b/src/constants.rs index 7bb6f0c..57c8b40 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -8,7 +8,15 @@ pub const NLEN: usize = curve_NLEN; pub const BIG_NUM_BITS: usize = BASEBITS; // Byte size of element in group G1, 1 extra byte for compression flag -pub const FIELD_ELEMENT_SIZE: usize = MODBYTES; +pub const FIELD_ORDER_ELEMENT_SIZE: usize = MODBYTES; +#[cfg(feature = "bls381")] +pub const CURVE_ORDER_ELEMENT_SIZE: usize = 32; +#[cfg(feature = "bn254")] +pub const CURVE_ORDER_ELEMENT_SIZE: usize = 28; +#[cfg(feature = "secp256k1")] +pub const CURVE_ORDER_ELEMENT_SIZE: usize = 28; +#[cfg(feature = "ed25519")] +pub const CURVE_ORDER_ELEMENT_SIZE: usize = 28; // Byte size of element in group G1, 1 extra byte for compression flag pub const GROUP_G1_SIZE: usize = (2 * MODBYTES + 1) as usize; @@ -19,14 +27,6 @@ pub const FIELD_ELEMENT_ZERO: BigNum = BigNum { w: [0; NLEN] }; lazy_static! { pub static ref GENERATOR_G1: GroupG1 = GroupG1::generator(); - pub static ref MODULUS_BITS: usize = MODULUS.nbits(); - pub static ref MODULUS_MINUS_1_DIV_2: BigNum = { - let mut order = MODULUS; - order.dec(1); - order.shr(1); - order - }; - pub static ref CURVE_ORDER_BIT_SIZE: usize = CURVE_ORDER.nbits(); pub static ref BARRETT_REDC_K: usize = MODULUS.nbits(); pub static ref BARRETT_REDC_U: BigNum = { let k = CURVE_ORDER.nbits(); diff --git a/src/field_elem.rs b/src/curve_order_elem.rs similarity index 57% rename from src/field_elem.rs rename to src/curve_order_elem.rs index 3f5f34f..7a35781 100644 --- a/src/field_elem.rs +++ b/src/curve_order_elem.rs @@ -1,32 +1,36 @@ +//! Represents an element where the operations are computed mod q where +//! q is the curve order use rand::{CryptoRng, RngCore}; use crate::constants::{ - BARRETT_REDC_K, BARRETT_REDC_U, BARRETT_REDC_V, BIG_NUM_BITS, CURVE_ORDER, FIELD_ELEMENT_SIZE, NLEN, - CURVE_ORDER_MINUS_1_DIV_2 + BARRETT_REDC_K, BARRETT_REDC_U, BARRETT_REDC_V, BIG_NUM_BITS, CURVE_ORDER, FIELD_ORDER_ELEMENT_SIZE, CURVE_ORDER_ELEMENT_SIZE, NLEN + }; use crate::errors::{SerzDeserzError, ValueError}; -use crate::signum::Sgn0; use crate::types::{BigNum, DoubleBigNum, Limb}; -use crate::utils::{barrett_reduction, get_seeded_rng, get_seeded_rng_with_rng, hash_msg}; -use amcl::rand::RAND; +use crate::utils::barrett_reduction; + +use sha3::digest::{ExtendableOutput, Input, XofReader}; +use sha3::Shake256; + use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; -use std::ops::{Add, AddAssign, Index, IndexMut, Mul, Neg, RangeBounds, Sub, SubAssign}; +use std::convert::TryFrom; use std::slice::Iter; +use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign, Index, IndexMut, RangeBounds}; -use serde::de::{Deserialize, Deserializer, Error as DError, Visitor}; -use serde::ser::{Serialize, Serializer}; - -use crate::rayon::iter::IntoParallelRefMutIterator; +use serde::{Serialize, Deserialize, Serializer, Deserializer}; +use serde::de::{Error as DError, Visitor}; +use rand::prelude::*; use rayon::prelude::*; use zeroize::Zeroize; #[macro_export] -macro_rules! add_field_elems { +macro_rules! add_curve_order_elems { ( $( $elem:expr ),* ) => { { - let mut sum = FieldElement::new(); + let mut sum = CurveOrderElement::new(); $( sum += $elem; )* @@ -36,77 +40,89 @@ macro_rules! add_field_elems { } #[derive(Clone, Debug)] -pub struct FieldElement { +pub struct CurveOrderElement { value: BigNum, } -impl fmt::Display for FieldElement { +impl fmt::Display for CurveOrderElement { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.value.fmt(f) } } -impl Hash for FieldElement { +impl Hash for CurveOrderElement { fn hash(&self, state: &mut H) { - let mut bytes: [u8; FIELD_ELEMENT_SIZE] = [0; FIELD_ELEMENT_SIZE]; + let mut bytes: [u8; FIELD_ORDER_ELEMENT_SIZE] = [0; FIELD_ORDER_ELEMENT_SIZE]; self.write_to_slice_unchecked(&mut bytes); state.write(&bytes) } } -impl Default for FieldElement { +impl Default for CurveOrderElement { fn default() -> Self { Self::new() } } -impl Zeroize for FieldElement { +impl Zeroize for CurveOrderElement { fn zeroize(&mut self) { self.value.w.zeroize(); } } -impl Drop for FieldElement { +impl Drop for CurveOrderElement { fn drop(&mut self) { self.zeroize() } } -/// Represents an element of the prime field of the curve. All operations are done modulo the curve order -impl FieldElement { - /// Creates a new field element with value 0 +/// Represents an element of the prime order of the curve. All operations are done modulo the curve order +impl CurveOrderElement { + /// Creates a new curve order element with value 0 pub fn new() -> Self { Self { value: BigNum::new(), } } + /// Creates a new curve order element with value 0 pub fn zero() -> Self { Self { value: BigNum::new(), } } + /// Creates a new curve order element with value 1 pub fn one() -> Self { Self { value: BigNum::new_int(1), } } + /// Creates a new curve order element with value -1 mod q pub fn minus_one() -> Self { let mut o = Self::one(); o.negate(); o } - /// Return a random non-zero field element + /// Return a random non-zero curve order element pub fn random() -> Self { - Self::random_field_element().into() + let mut rng = thread_rng(); + Self::random_using_rng(&mut rng) } - /// Return a random non-zero field element using the given random number generator + /// Return a random non-zero curve order element using the given random number generator pub fn random_using_rng(rng: &mut R) -> Self { - Self::random_field_element_using_rng(rng).into() + let mut data = [0u8; 2 * CURVE_ORDER_ELEMENT_SIZE]; + rng.fill_bytes(&mut data); + let mut n = DoubleBigNum::new(); + + for b in data.iter() { + n.shl(8); + n.w[0] += *b as Limb; + } + n.dmod(&CURVE_ORDER).into() } pub fn is_zero(&self) -> bool { @@ -118,32 +134,30 @@ impl FieldElement { } /// Return bytes in MSB form - pub fn to_bytes(&self) -> Vec { - let mut bytes: [u8; FIELD_ELEMENT_SIZE] = [0; FIELD_ELEMENT_SIZE]; + pub fn to_bytes(&self) -> [u8; FIELD_ORDER_ELEMENT_SIZE] { + let mut bytes: [u8; FIELD_ORDER_ELEMENT_SIZE] = [0; FIELD_ORDER_ELEMENT_SIZE]; self.write_to_slice_unchecked(&mut bytes); - bytes.to_vec() + bytes } - /// Expects bytes in MSB form - pub fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != FIELD_ELEMENT_SIZE { - return Err(SerzDeserzError::FieldElementBytesIncorrectSize( - bytes.len(), - FIELD_ELEMENT_SIZE, - )); - } - let mut n = BigNum::frombytes(bytes); - n.rmod(&CURVE_ORDER); - Ok(Self { value: n }) + /// Returns bytes in big-endian (MSB form) but removes all leading zeros + pub fn to_compressed_bytes(&self) -> [u8; CURVE_ORDER_ELEMENT_SIZE] { + let mut bytes = [0u8; FIELD_ORDER_ELEMENT_SIZE]; + self.write_to_slice_unchecked(&mut bytes); + + let removed_bytes = FIELD_ORDER_ELEMENT_SIZE - CURVE_ORDER_ELEMENT_SIZE; + let mut out = [0u8; CURVE_ORDER_ELEMENT_SIZE]; + out.copy_from_slice(&bytes[removed_bytes..]); + out } /// Writes bytes in MSB form to given slice. Raises exception when given slice is not of /// desired length. pub fn write_to_slice(&self, target: &mut [u8]) -> Result<(), SerzDeserzError> { - if target.len() != FIELD_ELEMENT_SIZE { + if target.len() != FIELD_ORDER_ELEMENT_SIZE { return Err(SerzDeserzError::FieldElementBytesIncorrectSize( target.len(), - FIELD_ELEMENT_SIZE, + FIELD_ORDER_ELEMENT_SIZE, )); } self.write_to_slice_unchecked(target); @@ -167,66 +181,81 @@ impl FieldElement { self.value.norm(); } - /// Hash an arbitrary sized message using SHAKE and return output as a field element + /// Hash an arbitrary sized message using SHAKE and return output as a curve order element pub fn from_msg_hash(msg: &[u8]) -> Self { - // TODO: Ensure result is not 0 - let h = &hash_msg(msg); - h.into() + let mut data = [0u8; 2 * CURVE_ORDER_ELEMENT_SIZE]; + let mut hasher = Shake256::default(); + hasher.input(&msg); + hasher.xof_result().read(&mut data); + let mut d = DoubleBigNum::new(); + for b in data.iter() { + d.shl(8); + d.w[0] += *b as Limb; + } + + d.dmod(&CURVE_ORDER).into() } - /// Add a field element to itself. `self = self + b` + /// Add a curve order element to itself. `self = self + b` pub fn add_assign_(&mut self, b: &Self) { // Not using `self.plus` to avoid cloning. Breaking the abstraction a bit for performance. self.value.add(&b.value); self.value.rmod(&CURVE_ORDER); + self.value.norm(); } - /// Subtract a field element from itself. `self = self - b` + /// Subtract a curve order element from itself. `self = self - b` pub fn sub_assign_(&mut self, b: &Self) { // Not using `self.minus` to avoid cloning. Breaking the abstraction a bit for performance. let neg_b = BigNum::modneg(&b.value, &CURVE_ORDER); self.value.add(&neg_b); self.value.rmod(&CURVE_ORDER); + self.value.norm(); } - /// Return sum of a field element and itself. `self + b` + /// Return sum of a curve order element and itself. `self + b` pub fn plus(&self, b: &Self) -> Self { let mut sum = self.value.clone(); sum.add(&b.value); sum.rmod(&CURVE_ORDER); + sum.norm(); sum.into() } - /// Return difference of a field element and itself. `self - b` + /// Return difference of a curve order element and itself. `self - b` pub fn minus(&self, b: &Self) -> Self { let mut sum = self.value.clone(); let neg_b = BigNum::modneg(&b.value, &CURVE_ORDER); sum.add(&neg_b); sum.rmod(&CURVE_ORDER); + sum.norm(); sum.into() } - /// Multiply 2 field elements modulus the order of the curve. - /// (field_element_a * field_element_b) % curve_order + /// Multiply 2 curve order elements modulus the order of the curve. + /// (curve_order_element_a * curve_order_element_b) % curve_order pub fn multiply(&self, b: &Self) -> Self { - let d = BigNum::mul(&self.value, &b.value); - Self::reduce_dmod_curve_order(&d).into() + let mut res = BigNum::modmul(&self.value, &b.value, &CURVE_ORDER); + res.norm(); + res.into() } - /// Calculate square of a field element modulo the curve order, i.e `a^2 % curve_order` + /// Calculate square of a curve order element modulo the curve order, i.e `a^2 % curve_order` pub fn square(&self) -> Self { - let d = BigNum::sqr(&self.value); - Self::reduce_dmod_curve_order(&d).into() + let mut res = BigNum::modsqr(&self.value, &CURVE_ORDER); + res.norm(); + res.into() } /// Exponentiation modulo curve order, i.e. self^exp % CURVE_ORDER pub fn pow(&self, exp: &Self) -> Self { let mut base = self.value.clone(); - let res = base.powmod(&exp.value, &CURVE_ORDER); + let mut res = base.powmod(&exp.value, &CURVE_ORDER); + res.norm(); res.into() } - /// Return negative of field element + /// Return negative of curve order element pub fn negation(&self) -> Self { let zero = Self::zero(); zero.minus(&self) @@ -237,7 +266,7 @@ impl FieldElement { self.value = zero.minus(&self).value; } - /// Calculate inverse of a field element modulo the curve order, i.e `a^-1 % curve_order` + /// Calculate inverse of a curve order element modulo the curve order, i.e `a^-1 % curve_order` pub fn inverse(&self) -> Self { // Violating constant time guarantee until bug fixed in amcl if self.is_zero() { @@ -245,6 +274,7 @@ impl FieldElement { } let mut inv = self.value.clone(); inv.invmodp(&CURVE_ORDER); + inv.norm(); inv.into() } @@ -254,6 +284,7 @@ impl FieldElement { self.value = BigNum::new(); } else { self.value.invmodp(&CURVE_ORDER); + self.value.norm(); } } @@ -317,29 +348,6 @@ impl FieldElement { bits } - /// Return a random non-zero field element using given random number generator - fn random_field_element_using_rng(rng: &mut R) -> BigNum { - // initialise from at least 128 byte string of raw random entropy - let entropy_size = 256; - let mut r = get_seeded_rng_with_rng(entropy_size, rng); - Self::get_big_num_from_rand(&mut r) - } - - fn random_field_element() -> BigNum { - // initialise from at least 128 byte string of raw random entropy - let entropy_size = 256; - let mut r = get_seeded_rng(entropy_size); - Self::get_big_num_from_rand(&mut r) - } - - fn get_big_num_from_rand(r: &mut RAND) -> BigNum { - let mut n = BigNum::randomnum(&BigNum::new_big(&CURVE_ORDER), r); - while n.iszilch() { - n = BigNum::randomnum(&BigNum::new_big(&CURVE_ORDER), r); - } - n - } - /// Conversion to wNAF, i.e. windowed Non Adjacent form /// Taken from Guide to Elliptic Curve Cryptography book, "Algorithm 3.35 Computing the width-w NAF of a positive integer" with modification /// at step 2.1, if k_i >= 2^(w-1), k_i = k_i - 2^w @@ -349,7 +357,7 @@ impl FieldElement { // required so that the NAF digits fit in i8 debug_assert!(w <= 8); - // Working on the the underlying BIG to save the cost of to and from conversion with FieldElement + // Working on the the underlying BIG to save the cost of to and from conversion with CurveOrderElement let mut k = self.to_bignum(); let mut naf: Vec = vec![]; @@ -363,6 +371,7 @@ impl FieldElement { let mut b = k.clone(); // b = b % 2^w b.mod2m(w); + b.norm(); // Only the first limb is useful as b <2^w let mut u = b.w[0]; @@ -396,6 +405,7 @@ impl FieldElement { while !t.iszilch() { let mut d = t.clone(); d.mod2m(n); + d.norm(); base_repr.push(d.w[0] as u8); t.fshr(n); } @@ -406,10 +416,10 @@ impl FieldElement { pub fn from_power_of_2_base(repr: &[u8], n: usize) -> Self { debug_assert!(n <= 7); - let mut accum = FieldElement::zero(); - let mut factor = FieldElement::one().to_bignum(); + let mut accum = CurveOrderElement::zero(); + let mut factor = CurveOrderElement::one().to_bignum(); for i in 0..repr.len() { - accum += FieldElement::from(factor) * FieldElement::from(repr[i]); + accum += CurveOrderElement::from(factor) * CurveOrderElement::from(repr[i]); factor.fshl(n); } accum @@ -424,7 +434,7 @@ impl FieldElement { self.value.or(&other.value); } - /// Takes a bunch of field elements and returns the inverse of all field elements. + /// Takes a bunch of curve order elements and returns the inverse of all curve order elements. /// Also returns the product of all inverses as its computed as a side effect. /// For an input of n elements, rather than doing n inversions, does only 1 inversion but 3n multiplications. /// eg `batch_invert([a, b, c, d])` returns ([1/a, 1/b, 1/c, 1/d], 1/a * 1/b * 1/c * 1/d) @@ -445,7 +455,7 @@ impl FieldElement { // u = 1 / elems[0]*elems[1]*elems[2]*...elems[k-1] let all_inv = c[k - 1].inverse(); let mut u = all_inv.clone(); - let mut inverses = vec![FieldElement::one(); k]; + let mut inverses = vec![CurveOrderElement::one(); k]; for i in (1..k).rev() { inverses[i] = &u * &c[i - 1]; @@ -459,8 +469,11 @@ impl FieldElement { /// Returns hex string in big endian pub fn to_hex(&self) -> String { - // TODO: Make constant time. - self.to_bignum().to_hex() + use subtle_encoding::hex; + let mut bytes = vec![0u8; FIELD_ORDER_ELEMENT_SIZE]; + let mut v = self.value; + v.tobytes(bytes.as_mut_slice()); + String::from_utf8(hex::encode_upper(&bytes)).unwrap() } /// Create big number from hex string in big endian @@ -478,37 +491,23 @@ impl FieldElement { /// Parse given hex string as BigNum in constant time. pub fn parse_hex_as_bignum(val: String) -> Result { - // Logic almost copied from AMCL but with error handling and constant time execution. - // Constant time is important as hex is used during serialization and deserialization. - // A seemingly effortless solution is to filter string for errors and pad with 0s before - // passing to AMCL but that would be expensive as the string is scanned twice - + use subtle_encoding::hex; let mut val = val; // Given hex cannot be bigger than max byte size - if val.len() > FIELD_ELEMENT_SIZE * 2 { + if val.len() > FIELD_ORDER_ELEMENT_SIZE * 2 { return Err(SerzDeserzError::FieldElementBytesIncorrectSize( val.len(), - FIELD_ELEMENT_SIZE, + FIELD_ORDER_ELEMENT_SIZE, )); } // Pad the string for constant time parsing. - while val.len() < FIELD_ELEMENT_SIZE * 2 { + while val.len() < FIELD_ORDER_ELEMENT_SIZE * 2 { val.insert(0, '0'); } - let mut res = BigNum::new(); - for i in 0..val.len() { - match u8::from_str_radix(&val[i..i + 1], 16) { - Ok(n) => res.w[0] += n as Limb, - Err(_) => return Err(SerzDeserzError::RequiredHexChar), - } - if i == (val.len() - 1) { - break; - } - res.shl(4); - } - return Ok(res); + let bytes = hex::decode_upper(val.to_uppercase()).map_err(|_| SerzDeserzError::RequiredHexChar)?; + Ok(BigNum::frombytes(bytes.as_slice())) } ///If c is False, cmove returns self, otherwise it returns b. @@ -518,66 +517,47 @@ impl FieldElement { res.into() } - /// returns either +1 or -1 indicating the - /// "sign" of x, where sgn0(x) == -1 just when x is "negative". In - /// other words, this function always considers 0 to be positive. - pub fn sgn0(&self) -> Sgn0 { - if self.value > *CURVE_ORDER_MINUS_1_DIV_2 { - Sgn0::Negative - } else { - Sgn0::NonNegative - } - } - - pub fn negate_if(&self, sgn: Sgn0) -> Self { - if sgn == Sgn0::Negative { - -self.clone() - } else { - self.clone() - } - } - /// Use this instead of static ref and new_int. This allows for initialization at compile time - pub const fn from_array(w: [Limb; NLEN]) -> FieldElement { - FieldElement { value: BigNum { w } } + pub const fn from_array(w: [Limb; NLEN]) -> CurveOrderElement { + CurveOrderElement { value: BigNum { w } } } } -impl Serialize for FieldElement { +impl Serialize for CurveOrderElement { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - serializer.serialize_newtype_struct("FieldElement", &self.to_hex()) + serializer.serialize_newtype_struct("CurveOrderElement", &self.to_hex()) } } -impl<'a> Deserialize<'a> for FieldElement { +impl<'a> Deserialize<'a> for CurveOrderElement { fn deserialize(deserializer: D) -> Result where D: Deserializer<'a>, { - struct FieldElementVisitor; + struct CurveOrderElementVisitor; - impl<'a> Visitor<'a> for FieldElementVisitor { - type Value = FieldElement; + impl<'a> Visitor<'a> for CurveOrderElementVisitor { + type Value = CurveOrderElement; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("expected FieldElement") + formatter.write_str("expected CurveOrderElement") } - fn visit_str(self, value: &str) -> Result + fn visit_str(self, value: &str) -> Result where E: DError, { - Ok(FieldElement::from_hex(value.to_string()).map_err(DError::custom)?) + Ok(CurveOrderElement::from_hex(value.to_string()).map_err(DError::custom)?) } } - deserializer.deserialize_str(FieldElementVisitor) + deserializer.deserialize_str(CurveOrderElementVisitor) } } -impl From for FieldElement { +impl From for CurveOrderElement { fn from(x: u8) -> Self { Self { value: BigNum::new_int(x as isize), @@ -585,7 +565,7 @@ impl From for FieldElement { } } -impl From for FieldElement { +impl From for CurveOrderElement { fn from(x: u32) -> Self { Self { value: BigNum::new_int(x as isize), @@ -593,7 +573,7 @@ impl From for FieldElement { } } -impl From for FieldElement { +impl From for CurveOrderElement { fn from(x: u64) -> Self { Self { value: BigNum::new_int(x as isize), @@ -601,7 +581,7 @@ impl From for FieldElement { } } -impl From for FieldElement { +impl From for CurveOrderElement { fn from(x: i32) -> Self { Self { value: BigNum::new_int(x as isize), @@ -609,36 +589,71 @@ impl From for FieldElement { } } -impl From for FieldElement { +impl From for CurveOrderElement { fn from(x: BigNum) -> Self { Self { value: x } } } -impl From<&[u8; FIELD_ELEMENT_SIZE]> for FieldElement { - fn from(x: &[u8; FIELD_ELEMENT_SIZE]) -> Self { - let mut n = BigNum::frombytes(x); +impl From<[u8; FIELD_ORDER_ELEMENT_SIZE]> for CurveOrderElement { + fn from(x: [u8; FIELD_ORDER_ELEMENT_SIZE]) -> Self { + Self::from(&x) + } +} + +impl From<&[u8; FIELD_ORDER_ELEMENT_SIZE]> for CurveOrderElement { + fn from(x: &[u8; FIELD_ORDER_ELEMENT_SIZE]) -> Self { + let mut n = BigNum::frombytes(&x[..]); n.rmod(&CURVE_ORDER); Self { value: n } } } -impl PartialEq for FieldElement { - fn eq(&self, other: &FieldElement) -> bool { +impl From<[u8; CURVE_ORDER_ELEMENT_SIZE]> for CurveOrderElement { + fn from(x: [u8; CURVE_ORDER_ELEMENT_SIZE]) -> Self { + Self::from(&x) + } +} + +impl From<&[u8; CURVE_ORDER_ELEMENT_SIZE]> for CurveOrderElement { + fn from(x: &[u8; CURVE_ORDER_ELEMENT_SIZE]) -> Self { + let leading_bytes = FIELD_ORDER_ELEMENT_SIZE - CURVE_ORDER_ELEMENT_SIZE; + let mut bytes = [0u8; FIELD_ORDER_ELEMENT_SIZE]; + bytes[leading_bytes..].copy_from_slice(&x[..]); + let mut n = BigNum::frombytes(&bytes[..]); + n.rmod(&CURVE_ORDER); + Self { value: n } + } +} + +impl TryFrom<&[u8]> for CurveOrderElement { + type Error = SerzDeserzError; + + fn try_from(bytes: &[u8]) -> Result { + match bytes.len() { + FIELD_ORDER_ELEMENT_SIZE => Ok(Self::from(*array_ref![bytes, 0, FIELD_ORDER_ELEMENT_SIZE])), + CURVE_ORDER_ELEMENT_SIZE => Ok(Self::from(*array_ref![bytes, 0, CURVE_ORDER_ELEMENT_SIZE])), + _ => Err(SerzDeserzError::FieldElementBytesIncorrectSize(bytes.len(), FIELD_ORDER_ELEMENT_SIZE)) + } + } +} + +impl PartialEq for CurveOrderElement { + fn eq(&self, other: &CurveOrderElement) -> bool { BigNum::comp(&self.value, &other.value) == 0 } } -impl PartialOrd for FieldElement { - fn partial_cmp(&self, other: &FieldElement) -> Option { +impl PartialOrd for CurveOrderElement { + fn partial_cmp(&self, other: &CurveOrderElement) -> Option { Some(self.cmp(other)) } } -impl Eq for FieldElement {} +impl Eq for CurveOrderElement {} -impl Ord for FieldElement { - fn cmp(&self, other: &FieldElement) -> Ordering { +impl Ord for CurveOrderElement { + fn cmp(&self, other: &CurveOrderElement) -> Ordering { match BigNum::comp(&self.value, &other.value) { 0 => Ordering::Equal, -1 => Ordering::Less, @@ -647,7 +662,7 @@ impl Ord for FieldElement { } } -impl Add for FieldElement { +impl Add for CurveOrderElement { type Output = Self; fn add(self, other: Self) -> Self { @@ -655,41 +670,41 @@ impl Add for FieldElement { } } -impl Add for &FieldElement { - type Output = FieldElement; +impl Add for &CurveOrderElement { + type Output = CurveOrderElement; - fn add(self, other: FieldElement) -> FieldElement { + fn add(self, other: CurveOrderElement) -> CurveOrderElement { self.plus(&other) } } -impl<'a> Add<&'a FieldElement> for FieldElement { +impl<'a> Add<&'a CurveOrderElement> for CurveOrderElement { type Output = Self; - fn add(self, other: &'a FieldElement) -> Self { + fn add(self, other: &'a CurveOrderElement) -> Self { self.plus(other) } } -impl<'a> Add<&'a FieldElement> for &FieldElement { - type Output = FieldElement; - fn add(self, other: &'a FieldElement) -> FieldElement { +impl<'a> Add<&'a CurveOrderElement> for &CurveOrderElement { + type Output = CurveOrderElement; + fn add(self, other: &'a CurveOrderElement) -> CurveOrderElement { self.plus(other) } } -impl AddAssign for FieldElement { +impl AddAssign for CurveOrderElement { fn add_assign(&mut self, other: Self) { self.add_assign_(&other) } } -impl<'a> AddAssign<&'a FieldElement> for FieldElement { - fn add_assign(&mut self, other: &'a FieldElement) { +impl<'a> AddAssign<&'a CurveOrderElement> for CurveOrderElement { + fn add_assign(&mut self, other: &'a CurveOrderElement) { self.add_assign_(other) } } -impl Sub for FieldElement { +impl Sub for CurveOrderElement { type Output = Self; fn sub(self, other: Self) -> Self { @@ -697,43 +712,43 @@ impl Sub for FieldElement { } } -impl Sub for &FieldElement { - type Output = FieldElement; +impl Sub for &CurveOrderElement { + type Output = CurveOrderElement; - fn sub(self, other: FieldElement) -> FieldElement { + fn sub(self, other: CurveOrderElement) -> CurveOrderElement { self.minus(&other) } } -impl<'a> Sub<&'a FieldElement> for FieldElement { +impl<'a> Sub<&'a CurveOrderElement> for CurveOrderElement { type Output = Self; - fn sub(self, other: &'a FieldElement) -> Self { + fn sub(self, other: &'a CurveOrderElement) -> Self { self.minus(&other) } } -impl<'a> Sub<&'a FieldElement> for &FieldElement { - type Output = FieldElement; +impl<'a> Sub<&'a CurveOrderElement> for &CurveOrderElement { + type Output = CurveOrderElement; - fn sub(self, other: &'a FieldElement) -> FieldElement { + fn sub(self, other: &'a CurveOrderElement) -> CurveOrderElement { self.minus(&other) } } -impl SubAssign for FieldElement { +impl SubAssign for CurveOrderElement { fn sub_assign(&mut self, other: Self) { self.sub_assign_(&other) } } -impl<'a> SubAssign<&'a FieldElement> for FieldElement { +impl<'a> SubAssign<&'a CurveOrderElement> for CurveOrderElement { fn sub_assign(&mut self, other: &'a Self) { self.sub_assign_(other) } } -impl Mul for FieldElement { +impl Mul for CurveOrderElement { type Output = Self; fn mul(self, other: Self) -> Self { @@ -741,31 +756,31 @@ impl Mul for FieldElement { } } -impl Mul for &FieldElement { - type Output = FieldElement; +impl Mul for &CurveOrderElement { + type Output = CurveOrderElement; - fn mul(self, other: FieldElement) -> FieldElement { + fn mul(self, other: CurveOrderElement) -> CurveOrderElement { self.multiply(&other) } } -impl<'a> Mul<&'a FieldElement> for FieldElement { - type Output = FieldElement; +impl<'a> Mul<&'a CurveOrderElement> for CurveOrderElement { + type Output = CurveOrderElement; - fn mul(self, other: &'a FieldElement) -> FieldElement { + fn mul(self, other: &'a CurveOrderElement) -> CurveOrderElement { self.multiply(other) } } -impl<'a> Mul<&'a FieldElement> for &FieldElement { - type Output = FieldElement; +impl<'a> Mul<&'a CurveOrderElement> for &CurveOrderElement { + type Output = CurveOrderElement; - fn mul(self, other: &'a FieldElement) -> FieldElement { + fn mul(self, other: &'a CurveOrderElement) -> CurveOrderElement { self.multiply(other) } } -impl Neg for FieldElement { +impl Neg for CurveOrderElement { type Output = Self; fn neg(self) -> Self::Output { @@ -773,8 +788,8 @@ impl Neg for FieldElement { } } -impl Neg for &FieldElement { - type Output = FieldElement; +impl Neg for &CurveOrderElement { + type Output = CurveOrderElement; fn neg(self) -> Self::Output { self.negation() @@ -782,36 +797,34 @@ impl Neg for &FieldElement { } #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct FieldElementVector { - elems: Vec, -} +pub struct CurveOrderElementVector(pub Vec); -impl FieldElementVector { +impl CurveOrderElementVector { /// Creates a new field element vector with each element being 0 // FIXME: size should have a type like u64 since usize can be small on older/smaller machines. This code // is less likely to be used on older/smaller machines though pub fn new(size: usize) -> Self { - Self { - elems: (0..size) + Self ( + (0..size) .into_par_iter() - .map(|_| FieldElement::new()) - .collect(), - } + .map(|_| CurveOrderElement::new()) + .collect() + ) } /// Generate a Vandermonde vector of field elements as: - /// FieldElementVector::new_vandermonde_vector(k, n) => vec![1, k, k^2, k^3, ... k^n-1] - /// FieldElementVector::new_vandermonde_vector(0, n) => vec![0, 0, ... n times] - pub fn new_vandermonde_vector(elem: &FieldElement, size: usize) -> Self { + /// CurveOrderElementVector::new_vandermonde_vector(k, n) => vec![1, k, k^2, k^3, ... k^n-1] + /// CurveOrderElementVector::new_vandermonde_vector(0, n) => vec![0, 0, ... n times] + pub fn new_vandermonde_vector(elem: &CurveOrderElement, size: usize) -> Self { if size == 0 { Self::new(0) } else if elem.is_zero() { Self::new(size) } else if elem.is_one() { - vec![FieldElement::one(); size].into() + vec![CurveOrderElement::one(); size].into() } else { - let mut v = Vec::::with_capacity(size); - v.push(FieldElement::one()); + let mut v = Vec::::with_capacity(size); + v.push(CurveOrderElement::one()); for i in 1..size { v.push(&v[i - 1] * elem); } @@ -820,70 +833,68 @@ impl FieldElementVector { } pub fn with_capacity(capacity: usize) -> Self { - Self { - elems: Vec::::with_capacity(capacity), - } + Self (Vec::::with_capacity(capacity)) } /// Get a vector of random field elements pub fn random(size: usize) -> Self { (0..size) .into_par_iter() - .map(|_| FieldElement::random()) - .collect::>() + .map(|_| CurveOrderElement::random()) + .collect::>() .into() } - pub fn as_slice(&self) -> &[FieldElement] { - self.elems.as_slice() + pub fn as_slice(&self) -> &[CurveOrderElement] { + self.0.as_slice() } - pub fn as_mut_slice(&mut self) -> &mut [FieldElement] { - self.elems.as_mut_slice() + pub fn as_mut_slice(&mut self) -> &mut [CurveOrderElement] { + self.0.as_mut_slice() } pub fn len(&self) -> usize { - self.elems.len() + self.0.len() } - pub fn push(&mut self, value: FieldElement) { - self.elems.push(value) + pub fn push(&mut self, value: CurveOrderElement) { + self.0.push(value) } pub fn append(&mut self, other: &mut Self) { - self.elems.append(&mut other.elems) + self.0.append(&mut other.0) } - pub fn pop(&mut self) -> Option { - self.elems.pop() + pub fn pop(&mut self) -> Option { + self.0.pop() } - pub fn insert(&mut self, index: usize, element: FieldElement) { - self.elems.insert(index, element) + pub fn insert(&mut self, index: usize, element: CurveOrderElement) { + self.0.insert(index, element) } - pub fn remove(&mut self, index: usize) -> FieldElement { - self.elems.remove(index) + pub fn remove(&mut self, index: usize) -> CurveOrderElement { + self.0.remove(index) } /// Multiply each element of the vector with a given field /// element `n` (scale the vector). Modifies the vector. - pub fn scale(&mut self, n: &FieldElement) { - self.elems.as_mut_slice().par_iter_mut().for_each(|e| { + pub fn scale(&mut self, n: &CurveOrderElement) { + self.0.as_mut_slice().par_iter_mut().for_each(|e| { *e = e.multiply(n); }) } /// Multiply each element of the vector with a given field /// element `n` to create a new vector - pub fn scaled_by(&self, n: &FieldElement) -> Self { + pub fn scaled_by(&self, n: &CurveOrderElement) -> Self { let mut scaled = self.clone(); scaled.scale(n); scaled.into() } /// Add 2 vectors of field elements - pub fn plus(&self, b: &FieldElementVector) -> Result { + pub fn plus(&self, b: &CurveOrderElementVector) -> Result { check_vector_size_for_equality!(self, b)?; let mut sum_vector = Self::new(self.len()); sum_vector @@ -895,7 +906,7 @@ impl FieldElementVector { } /// Subtract 2 vectors of field elements - pub fn minus(&self, b: &FieldElementVector) -> Result { + pub fn minus(&self, b: &CurveOrderElementVector) -> Result { check_vector_size_for_equality!(self, b)?; let mut diff_vector = Self::new(self.len()); diff_vector @@ -907,18 +918,18 @@ impl FieldElementVector { } /// Compute sum of all elements of a vector - pub fn sum(&self) -> FieldElement { + pub fn sum(&self) -> CurveOrderElement { self.as_slice() .par_iter() .cloned() - .reduce(|| FieldElement::new(), |a, b| a + b) + .reduce(|| CurveOrderElement::new(), |a, b| a + b) } /// Computes inner product of 2 vectors of field elements /// [a1, a2, a3, ...field elements].[b1, b2, b3, ...field elements] = (a1*b1 + a2*b2 + a3*b3) % curve_order - pub fn inner_product(&self, b: &FieldElementVector) -> Result { + pub fn inner_product(&self, b: &CurveOrderElementVector) -> Result { check_vector_size_for_equality!(self, b)?; - let r = (0..b.len()).into_par_iter().map(|i| (&self[i] * &b[i])).reduce(|| FieldElement::new(), |a, b| a + b); + let r = (0..b.len()).into_par_iter().map(|i| (&self[i] * &b[i])).reduce(|| CurveOrderElement::new(), |a, b| a + b); Ok(r) } @@ -927,8 +938,8 @@ impl FieldElementVector { /// Here `o` denotes multiply operation pub fn hadamard_product( &self, - b: &FieldElementVector, - ) -> Result { + b: &CurveOrderElementVector, + ) -> Result { check_vector_size_for_equality!(self, b)?; let mut hadamard_product = Self::new(self.len()); hadamard_product @@ -949,55 +960,55 @@ impl FieldElementVector { pub(crate) fn splice(&mut self, range: R, replace_with: I) where R: RangeBounds, - I: IntoIterator, + I: IntoIterator, { - self.elems.splice(range, replace_with); + self.0.splice(range, replace_with); } - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter { self.as_slice().iter() } } -impl From> for FieldElementVector { - fn from(x: Vec) -> Self { - Self { elems: x } +impl From> for CurveOrderElementVector { + fn from(x: Vec) -> Self { + Self(x) } } -impl From<&[FieldElement]> for FieldElementVector { - fn from(x: &[FieldElement]) -> Self { - Self { elems: x.to_vec() } +impl From<&[CurveOrderElement]> for CurveOrderElementVector { + fn from(x: &[CurveOrderElement]) -> Self { + Self(x.to_vec()) } } -impl Into> for FieldElementVector { - fn into(self) -> Vec { - self.elems +impl Into> for CurveOrderElementVector { + fn into(self) -> Vec { + self.0 } } -impl<'a> Into<&'a [FieldElement]> for &'a FieldElementVector { - fn into(self) -> &'a [FieldElement] { - &self.elems +impl<'a> Into<&'a [CurveOrderElement]> for &'a CurveOrderElementVector { + fn into(self) -> &'a [CurveOrderElement] { + &self.0 } } -impl Index for FieldElementVector { - type Output = FieldElement; +impl Index for CurveOrderElementVector { + type Output = CurveOrderElement; - fn index(&self, idx: usize) -> &FieldElement { - &self.elems[idx] + fn index(&self, idx: usize) -> &CurveOrderElement { + &self.0[idx] } } -impl IndexMut for FieldElementVector { - fn index_mut(&mut self, idx: usize) -> &mut FieldElement { - &mut self.elems[idx] +impl IndexMut for CurveOrderElementVector { + fn index_mut(&mut self, idx: usize) -> &mut CurveOrderElement { + &mut self.0[idx] } } -impl PartialEq for FieldElementVector { +impl PartialEq for CurveOrderElementVector { fn eq(&self, other: &Self) -> bool { if self.len() != other.len() { return false; @@ -1011,30 +1022,30 @@ impl PartialEq for FieldElementVector { } } -impl IntoIterator for FieldElementVector { - type Item = FieldElement; - type IntoIter = ::std::vec::IntoIter; +impl IntoIterator for CurveOrderElementVector { + type Item = CurveOrderElement; + type IntoIter = ::std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { - self.elems.into_iter() + self.0.into_iter() } } -impl AsRef<[FieldElement]> for FieldElementVector { - fn as_ref(&self) -> &[FieldElement] { - self.elems.as_slice() +impl AsRef<[CurveOrderElement]> for CurveOrderElementVector { + fn as_ref(&self) -> &[CurveOrderElement] { + self.0.as_slice() } } // TODO: Implement add/sub/mul ops but need some way to handle error when vectors are of different length pub fn multiply_row_vector_with_matrix( - vector: &FieldElementVector, - matrix: &Vec, -) -> Result { + vector: &CurveOrderElementVector, + matrix: &Vec, +) -> Result { check_vector_size_for_equality!(vector, matrix)?; let out_len = matrix[0].len(); - let mut out = FieldElementVector::new(out_len); + let mut out = CurveOrderElementVector::new(out_len); for i in 0..out_len { for j in 0..vector.len() { out[i] += &vector[j] * &matrix[j][i]; @@ -1055,18 +1066,18 @@ mod test { fn test_to_and_from_bytes() { let mut rng = rand::thread_rng(); for _ in 0..100 { - let x = FieldElement::random_using_rng(&mut rng); + let x = CurveOrderElement::random_using_rng(&mut rng); - let mut bytes_x: [u8; FIELD_ELEMENT_SIZE] = [0; FIELD_ELEMENT_SIZE]; + let mut bytes_x: [u8; FIELD_ORDER_ELEMENT_SIZE] = [0; FIELD_ORDER_ELEMENT_SIZE]; x.write_to_slice(&mut bytes_x).unwrap(); - let y = FieldElement::from(&bytes_x); + let y = CurveOrderElement::from(&bytes_x); assert_eq!(x, y); - let z = FieldElement::from_bytes(&x.to_bytes()).unwrap(); + let z = CurveOrderElement::from(&x.to_bytes()); assert_eq!(x, z); - let y1 = FieldElement::random_using_rng(&mut rng); - let z1 = FieldElement::from_bytes(&y1.to_bytes()).unwrap(); + let y1 = CurveOrderElement::random_using_rng(&mut rng); + let z1 = CurveOrderElement::from(&y1.to_bytes()); assert_ne!(x, z1); } } @@ -1075,55 +1086,55 @@ mod test { fn test_equality() { for _ in 0..10 { // Very unlikely that 2 randomly chosen elements will be equal - let a = FieldElement::random(); - let b = FieldElement::random(); + let a = CurveOrderElement::random(); + let b = CurveOrderElement::random(); assert_ne!(&a, &b); } } #[test] - fn test_field_elem_multiplication() { - let a: FieldElement = 5u8.into(); - let b: FieldElement = 18u8.into(); - let c: FieldElement = 90u8.into(); + fn test_elem_multiplication() { + let a: CurveOrderElement = 5u8.into(); + let b: CurveOrderElement = 18u8.into(); + let c: CurveOrderElement = 90u8.into(); assert_eq!(a.multiply(&b), c); assert_eq!(a * b, c); } #[test] fn test_inversion() { - assert_eq!(FieldElement::zero().inverse(), FieldElement::zero()); - assert_eq!(FieldElement::one().inverse(), FieldElement::one()); - let mut zero = FieldElement::zero(); + assert_eq!(CurveOrderElement::zero().inverse(), CurveOrderElement::zero()); + assert_eq!(CurveOrderElement::one().inverse(), CurveOrderElement::one()); + let mut zero = CurveOrderElement::zero(); zero.inverse_mut(); - assert_eq!(zero, FieldElement::zero()); + assert_eq!(zero, CurveOrderElement::zero()); for _ in 0..10 { - let x = FieldElement::random(); + let x = CurveOrderElement::random(); let x_inv = x.inverse(); - assert_eq!(x * x_inv, FieldElement::one()) + assert_eq!(x * x_inv, CurveOrderElement::one()) } } #[test] fn test_pow() { for _ in 0..5 { - let base = FieldElement::random(); + let base = CurveOrderElement::random(); let base_sqr = base.square(); - assert_eq!(base.pow(&FieldElement::from(2u64)), base_sqr); + assert_eq!(base.pow(&CurveOrderElement::from(2u64)), base_sqr); let base_cube = &base_sqr * &base; - assert_eq!(base.pow(&FieldElement::from(3u64)), base_cube); + assert_eq!(base.pow(&CurveOrderElement::from(3u64)), base_cube); let base_4 = base_sqr.square(); - assert_eq!(base.pow(&FieldElement::from(4u64)), base_4); + assert_eq!(base.pow(&CurveOrderElement::from(4u64)), base_4); let base_5 = &base_4 * &base; - assert_eq!(base.pow(&FieldElement::from(5u64)), base_5); + assert_eq!(base.pow(&CurveOrderElement::from(5u64)), base_5); /*// Check base^r1 * base^r2 = base^(r1 + r2) - let r1 = FieldElement::random(); - let r2 = FieldElement::random(); + let r1 = CurveOrderElement::random(); + let r2 = CurveOrderElement::random(); let mut r3 = &r1 + &r2; assert_eq!(&r1 + &r2, r3); let x = &base.pow(&r1) * &base.pow(&r2); @@ -1136,24 +1147,24 @@ mod test { #[test] fn test_nth_bit() { - assert_eq!(FieldElement::one().nth_bit(0), 1); - assert_eq!(FieldElement::one().nth_bit(1), 0); - assert_eq!(FieldElement::one().nth_bit(2), 0); + assert_eq!(CurveOrderElement::one().nth_bit(0), 1); + assert_eq!(CurveOrderElement::one().nth_bit(1), 0); + assert_eq!(CurveOrderElement::one().nth_bit(2), 0); - assert_eq!(FieldElement::from(2u64).nth_bit(0), 0); - assert_eq!(FieldElement::from(2u64).nth_bit(1), 1); - assert_eq!(FieldElement::from(2u64).nth_bit(2), 0); - assert_eq!(FieldElement::from(2u64).nth_bit(3), 0); + assert_eq!(CurveOrderElement::from(2u64).nth_bit(0), 0); + assert_eq!(CurveOrderElement::from(2u64).nth_bit(1), 1); + assert_eq!(CurveOrderElement::from(2u64).nth_bit(2), 0); + assert_eq!(CurveOrderElement::from(2u64).nth_bit(3), 0); - assert_eq!(FieldElement::from(3u64).nth_bit(0), 1); - assert_eq!(FieldElement::from(3u64).nth_bit(1), 1); - assert_eq!(FieldElement::from(3u64).nth_bit(2), 0); - assert_eq!(FieldElement::from(3u64).nth_bit(3), 0); + assert_eq!(CurveOrderElement::from(3u64).nth_bit(0), 1); + assert_eq!(CurveOrderElement::from(3u64).nth_bit(1), 1); + assert_eq!(CurveOrderElement::from(3u64).nth_bit(2), 0); + assert_eq!(CurveOrderElement::from(3u64).nth_bit(3), 0); let mut rng = rand::thread_rng(); for _ in 0..10 { - let r = FieldElement::random(); + let r = CurveOrderElement::random(); let bits = r.to_bits(); // Check bits at 100 random indices for _ in 0..100 { @@ -1165,18 +1176,18 @@ mod test { #[test] fn test_or() { - let mut a = FieldElement::one(); - let b = FieldElement::from(2); + let mut a = CurveOrderElement::one(); + let b = CurveOrderElement::from(2); a.or(&b); - assert_eq!(a, FieldElement::from(3)); + assert_eq!(a, CurveOrderElement::from(3)); - let mut a = FieldElement::from(4); + let mut a = CurveOrderElement::from(4); a.or(&b); - assert_eq!(a, FieldElement::from(6)); + assert_eq!(a, CurveOrderElement::from(6)); for _ in 0..100 { - let r1 = FieldElement::random(); - let r2 = FieldElement::random(); + let r1 = CurveOrderElement::random(); + let r2 = CurveOrderElement::random(); // r3 = r1 | r2 let mut r3 = r1.clone(); r3.or(&r2); @@ -1197,120 +1208,112 @@ mod test { } #[test] - fn test_field_elements_inner_product() { - let a: FieldElementVector = vec![ - FieldElement::from(5), - FieldElement::one(), - FieldElement::from(100), - FieldElement::zero(), - ] - .into(); - let b: FieldElementVector = vec![ - FieldElement::from(18), - FieldElement::one(), - FieldElement::from(200), - FieldElement::zero(), - ] - .into(); - let c = FieldElement::from((90 + 1 + 200 * 100) as u32); + fn test_elements_inner_product() { + let a = CurveOrderElementVector(vec![ + CurveOrderElement::from(5), + CurveOrderElement::one(), + CurveOrderElement::from(100), + CurveOrderElement::zero(), + ]); + let b = CurveOrderElementVector(vec![ + CurveOrderElement::from(18), + CurveOrderElement::one(), + CurveOrderElement::from(200), + CurveOrderElement::zero(), + ]); + let c = CurveOrderElement::from((90 + 1 + 200 * 100) as u32); assert_eq!(a.inner_product(&b).unwrap(), c); } #[test] - fn test_field_elements_hadamard_product() { - let a: FieldElementVector = vec![ - FieldElement::from(5), - FieldElement::one(), - FieldElement::from(100), - FieldElement::zero(), - ] - .into(); - let b: FieldElementVector = vec![ - FieldElement::from(18), - FieldElement::one(), - FieldElement::from(200), - FieldElement::zero(), - ] - .into(); - let h: FieldElementVector = vec![ - FieldElement::from(90), - FieldElement::one(), - FieldElement::from(200 * 100), - FieldElement::zero(), - ] - .into(); - let c = FieldElement::from((90 + 1 + 200 * 100) as u32); + fn test_elements_hadamard_product() { + let a = CurveOrderElementVector(vec![ + CurveOrderElement::from(5), + CurveOrderElement::one(), + CurveOrderElement::from(100), + CurveOrderElement::zero(), + ]); + let b = CurveOrderElementVector(vec![ + CurveOrderElement::from(18), + CurveOrderElement::one(), + CurveOrderElement::from(200), + CurveOrderElement::zero(), + ]); + let h = CurveOrderElementVector(vec![ + CurveOrderElement::from(90), + CurveOrderElement::one(), + CurveOrderElement::from(200 * 100), + CurveOrderElement::zero(), + ]); + let c = CurveOrderElement::from((90 + 1 + 200 * 100) as u32); assert_eq!(a.hadamard_product(&b).unwrap(), h); assert_eq!(h.sum(), c); } #[test] - fn test_scale_field_element_vector() { - let a: FieldElementVector = vec![ - FieldElement::from(5), - FieldElement::from(1), - FieldElement::from(100), - FieldElement::from(0), - ] - .into(); - let n = FieldElement::from(3); + fn test_scale_element_vector() { + let a = CurveOrderElementVector(vec![ + CurveOrderElement::from(5), + CurveOrderElement::from(1), + CurveOrderElement::from(100), + CurveOrderElement::from(0), + ]); + let n = CurveOrderElement::from(3); let na = a.scaled_by(&n); - assert_eq!(na[0], FieldElement::from(5 * 3)); - assert_eq!(na[1], FieldElement::from(1 * 3)); - assert_eq!(na[2], FieldElement::from(100 * 3)); - assert_eq!(na[3], FieldElement::from(0)); + assert_eq!(na[0], CurveOrderElement::from(5 * 3)); + assert_eq!(na[1], CurveOrderElement::from(1 * 3)); + assert_eq!(na[2], CurveOrderElement::from(100 * 3)); + assert_eq!(na[3], CurveOrderElement::from(0)); } #[test] - fn test_add_field_element_vectors() { - let a: FieldElementVector = vec![ - FieldElement::from(5), - FieldElement::one(), - FieldElement::from(100), - FieldElement::zero(), - ] - .into(); - let b: FieldElementVector = vec![ - FieldElement::from(18), - FieldElement::one(), - FieldElement::from(200), - FieldElement::zero(), - ] - .into(); + fn test_add_element_vectors() { + let a = CurveOrderElementVector(vec![ + CurveOrderElement::from(5), + CurveOrderElement::one(), + CurveOrderElement::from(100), + CurveOrderElement::zero(), + ]); + let b = CurveOrderElementVector(vec![ + CurveOrderElement::from(18), + CurveOrderElement::one(), + CurveOrderElement::from(200), + CurveOrderElement::zero(), + ]); let c = a.plus(&b).unwrap(); - assert_eq!(c[0], FieldElement::from(5 + 18)); - assert_eq!(c[1], FieldElement::from(1 + 1)); - assert_eq!(c[2], FieldElement::from(100 + 200)); - assert_eq!(c[3], FieldElement::from(0)); + assert_eq!(c[0], CurveOrderElement::from(5 + 18)); + assert_eq!(c[1], CurveOrderElement::from(1 + 1)); + assert_eq!(c[2], CurveOrderElement::from(100 + 200)); + assert_eq!(c[3], CurveOrderElement::from(0)); } #[test] - fn test_field_elem_vandermonde_vector() { - let zero_vec = FieldElementVector::new_vandermonde_vector(&FieldElement::zero(), 5); + fn test_elem_vandermonde_vector() { + let zero_vec = CurveOrderElementVector::new_vandermonde_vector(&CurveOrderElement::zero(), 5); for i in 0..5 { assert!(zero_vec[i].is_zero()) } - let unit_vec = FieldElementVector::new_vandermonde_vector(&FieldElement::one(), 5); + let unit_vec = CurveOrderElementVector::new_vandermonde_vector(&CurveOrderElement::one(), 5); for i in 0..4 { assert!(unit_vec[i].is_one()) } - let two_vec = FieldElementVector::new_vandermonde_vector(&FieldElement::from(2u8), 10); + let two_vec = CurveOrderElementVector::new_vandermonde_vector(&CurveOrderElement::from(2u8), 10); let base = 2u32; for i in 0..10 { - assert_eq!(two_vec[i], FieldElement::from(base.pow(i as u32) as u32)); + assert_eq!(two_vec[i], CurveOrderElement::from(base.pow(i as u32) as u32)); } } #[test] fn test_to_bitvectors() { - let n = FieldElement::from(100u32); + let n = CurveOrderElement::from(100u32); assert_eq!(n.to_bitvectors(), vec![vec![0, 0, 1, 0, 0, 1, 1]]); let mut c = vec![0i64; NLEN]; c[0] = 2; c[1] = 100; - let m: FieldElement = BigNum::new_ints(&c).into(); + let m: CurveOrderElement = BigNum::new_ints(&c).into(); assert_eq!( m.to_bitvectors(), vec![vec![0, 1], vec![0, 0, 1, 0, 0, 1, 1]] @@ -1321,16 +1324,16 @@ mod test { fn test_to_bits() { let mut bits = vec![0, 1, 0, 1]; bits.append(&mut vec![0; BIG_NUM_BITS - 4]); - assert_eq!(FieldElement::from(10u32).to_bits(), bits); + assert_eq!(CurveOrderElement::from(10u32).to_bits(), bits); let mut bits = vec![0, 0, 1, 0, 0, 1, 1]; bits.append(&mut vec![0; BIG_NUM_BITS - 7]); - assert_eq!(FieldElement::from(100u32).to_bits(), bits); + assert_eq!(CurveOrderElement::from(100u32).to_bits(), bits); let mut c = vec![0i64; NLEN]; c[0] = 2; c[1] = 100; - let m: FieldElement = BigNum::new_ints(&c).into(); + let m: CurveOrderElement = BigNum::new_ints(&c).into(); let mut bits = vec![0, 1]; bits.append(&mut vec![0; BIG_NUM_BITS - 2]); bits.append(&mut vec![0, 0, 1, 0, 0, 1, 1]); @@ -1339,24 +1342,24 @@ mod test { } #[test] - fn test_negating_field_elems() { - let b = FieldElement::random(); + fn test_negating_elems() { + let b = CurveOrderElement::random(); let neg_b = -&b; assert_ne!(b, neg_b); let neg_neg_b = -&neg_b; assert_eq!(b, neg_neg_b); - assert_eq!(b + neg_b, FieldElement::zero()); + assert_eq!(b + neg_b, CurveOrderElement::zero()); } #[test] - fn test_field_elem_addition() { - let a = FieldElement::random(); - let b = FieldElement::random(); - let c = FieldElement::random(); + fn test_elem_addition() { + let a = CurveOrderElement::random(); + let b = CurveOrderElement::random(); + let c = CurveOrderElement::random(); let sum = &a + &b + &c; - let mut expected_sum = FieldElement::new(); + let mut expected_sum = CurveOrderElement::new(); expected_sum = expected_sum.plus(&a); expected_sum = expected_sum.plus(&b); expected_sum += &c; @@ -1364,14 +1367,14 @@ mod test { } #[test] - fn test_field_elem_subtraction() { - let a = FieldElement::random(); - let b = FieldElement::random(); - let c = FieldElement::random(); + fn test_elem_subtraction() { + let a = CurveOrderElement::random(); + let b = CurveOrderElement::random(); + let c = CurveOrderElement::random(); let sum = &a - &b - &c; - let mut expected_sum = FieldElement::new(); + let mut expected_sum = CurveOrderElement::new(); expected_sum = expected_sum.plus(&a); expected_sum = expected_sum - &b; expected_sum -= &c; @@ -1379,27 +1382,27 @@ mod test { } #[test] - fn test_static_field_elems() { - let zero = FieldElement::zero(); - let one = FieldElement::one(); - let minus_one = FieldElement::minus_one(); + fn test_static_elems() { + let zero = CurveOrderElement::zero(); + let one = CurveOrderElement::one(); + let minus_one = CurveOrderElement::minus_one(); assert_eq!(one + minus_one, zero); } #[test] - fn test_field_elem_to_from_base() { + fn test_elem_to_from_base() { for i in 0..4 { - let x = FieldElement::from(i as u8); + let x = CurveOrderElement::from(i as u8); let b = x.to_power_of_2_base(2); assert_eq!(b, vec![i]); - assert_eq!(x, FieldElement::from_power_of_2_base(&b, 2)); + assert_eq!(x, CurveOrderElement::from_power_of_2_base(&b, 2)); } for i in 0..8 { - let x = FieldElement::from(i as u8); + let x = CurveOrderElement::from(i as u8); let b = x.to_power_of_2_base(3); assert_eq!(b, vec![i]); - assert_eq!(x, FieldElement::from_power_of_2_base(&b, 3)); + assert_eq!(x, CurveOrderElement::from_power_of_2_base(&b, 3)); } for (n, expected_4) in vec![ @@ -1415,10 +1418,10 @@ mod test { vec![0, 1, 1, 0, 0, 2, 3, 0, 3, 0, 2, 0, 3, 0, 1, 0, 2], ), ] { - let x = FieldElement::from(n as u64); + let x = CurveOrderElement::from(n as u64); let b = x.to_power_of_2_base(2); assert_eq!(b, expected_4); - assert_eq!(x, FieldElement::from_power_of_2_base(&b, 2)); + assert_eq!(x, CurveOrderElement::from_power_of_2_base(&b, 2)); } for (n, expected_8) in vec![ @@ -1427,17 +1430,17 @@ mod test { (6719, vec![7, 7, 0, 5, 1]), (8911009812u64, vec![4, 2, 0, 4, 3, 6, 0, 1, 3, 2, 0, 1]), ] { - let x = FieldElement::from(n as u64); + let x = CurveOrderElement::from(n as u64); let b = x.to_power_of_2_base(3); assert_eq!(b, expected_8); - assert_eq!(x, FieldElement::from_power_of_2_base(&b, 3)); + assert_eq!(x, CurveOrderElement::from_power_of_2_base(&b, 3)); } for _ in 0..100 { - let x = FieldElement::random(); + let x = CurveOrderElement::random(); for base in 2..8 { let digits = x.to_power_of_2_base(base); - assert_eq!(x, FieldElement::from_power_of_2_base(&digits, base)); + assert_eq!(x, CurveOrderElement::from_power_of_2_base(&digits, base)); } } } @@ -1447,10 +1450,10 @@ mod test { // If the element can be added to HashSet or HashMap, it must be hashable. let mut set = HashSet::new(); let mut map = HashMap::new(); - let x = FieldElement::random(); + let x = CurveOrderElement::random(); set.insert(x.clone()); - let y = FieldElement::random(); - map.insert(y.clone(), FieldElement::random()); + let y = CurveOrderElement::random(); + map.insert(y.clone(), CurveOrderElement::random()); assert!(set.contains(&x)); assert!(map.contains_key(&y)); } @@ -1459,9 +1462,9 @@ mod test { fn timing_multiplication_inversion() { // Timing multiplication and inversion let count = 100; - let elems: Vec<_> = (0..count).map(|_| FieldElement::random()).collect(); + let elems: Vec<_> = (0..count).map(|_| CurveOrderElement::random()).collect(); - let mut res_mul = FieldElement::one(); + let mut res_mul = CurveOrderElement::one(); let mut start = Instant::now(); for e in &elems { res_mul = res_mul * e; @@ -1480,14 +1483,14 @@ mod test { println!("Inverse time for {} elems = {:?}", count, start.elapsed()); start = Instant::now(); - let (inverses_1, all_inv) = FieldElement::batch_invert(&elems); + let (inverses_1, all_inv) = CurveOrderElement::batch_invert(&elems); println!( "Batch inverse time for {} elems = {:?}", count, start.elapsed() ); - let mut expected_inv_product = FieldElement::one(); + let mut expected_inv_product = CurveOrderElement::one(); for i in 0..count { assert_eq!(inverses[i], inverses_1[i]); expected_inv_product = expected_inv_product * &inverses[i]; @@ -1497,10 +1500,10 @@ mod test { } #[test] - fn timing_field_elem_addition() { + fn timing_elem_addition() { let count = 100; - let points: Vec = (0..count).map(|_| FieldElement::random()).collect(); - let mut r = FieldElement::random(); + let points: Vec = (0..count).map(|_| CurveOrderElement::random()).collect(); + let mut r = CurveOrderElement::random(); let start = Instant::now(); for i in 0..count { r = &r + &points[i]; @@ -1509,13 +1512,13 @@ mod test { } #[test] - fn timing_field_elem_multiplication() { + fn timing_elem_multiplication() { let count = 1000; let l: Vec = (0..count) - .map(|_| FieldElement::random().to_bignum()) + .map(|_| CurveOrderElement::random().to_bignum()) .collect(); let r: Vec = (0..count) - .map(|_| FieldElement::random().to_bignum()) + .map(|_| CurveOrderElement::random().to_bignum()) .collect(); let mut o1 = vec![]; let mut o2 = vec![]; @@ -1569,9 +1572,9 @@ mod test { } #[test] - fn timing_field_elem_squaring() { + fn timing_elem_squaring() { let count = 1000; - let fs: Vec = (0..count).map(|_| FieldElement::random()).collect(); + let fs: Vec = (0..count).map(|_| CurveOrderElement::random()).collect(); let nums: Vec = fs.iter().map(|f| f.to_bignum()).collect(); let mut r1 = vec![]; let mut r2 = vec![]; @@ -1607,9 +1610,9 @@ mod test { #[test] fn test_parse_hex_as_bignum() { for _ in 0..100 { - let b = FieldElement::random().to_bignum(); + let b = CurveOrderElement::random().to_bignum(); let h = b.clone().to_hex(); - let b1 = FieldElement::parse_hex_as_bignum(h.clone()).unwrap(); + let b1 = CurveOrderElement::parse_hex_as_bignum(h.clone()).unwrap(); let b2 = BigNum::from_hex(h); assert_eq!(b, b2); assert_eq!(b, b1); @@ -1618,42 +1621,42 @@ mod test { #[test] fn test_parse_bad_hex_for_bignum() { - let r1 = FieldElement::random(); + let r1 = CurveOrderElement::random(); let mut h = r1.to_hex(); // Make hex string bigger h.insert(0, '0'); - assert!(h.len() > FIELD_ELEMENT_SIZE * 2); - assert!(FieldElement::parse_hex_as_bignum(h.clone()).is_err()); + assert!(h.len() > FIELD_ORDER_ELEMENT_SIZE * 2); + assert!(CurveOrderElement::parse_hex_as_bignum(h.clone()).is_err()); let mut h = r1.to_hex(); // Add non hex character h = h.replacen("0", "G", 1); - assert_eq!(h.len(), FIELD_ELEMENT_SIZE * 2); - assert!(FieldElement::parse_hex_as_bignum(h.clone()).is_err()); + assert_eq!(h.len(), FIELD_ORDER_ELEMENT_SIZE * 2); + assert!(CurveOrderElement::parse_hex_as_bignum(h.clone()).is_err()); } #[test] - fn test_hex_field_elem() { + fn test_hex_elem() { for _ in 0..1000 { - let r = FieldElement::random(); + let r = CurveOrderElement::random(); let h = r.to_hex(); - let r_ = FieldElement::from_hex(h).unwrap(); + let r_ = CurveOrderElement::from_hex(h).unwrap(); assert_eq!(r, r_); // Very unlikely that 2 randomly chosen elements will be equal - let s = FieldElement::random(); + let s = CurveOrderElement::random(); assert_ne!(r, s); } } #[test] - fn test_serialization_deserialization_field_elem() { + fn test_serialization_deserialization_elem() { #[derive(Serialize, Deserialize)] struct Temp { - val: FieldElement, + val: CurveOrderElement, } for _ in 0..100 { - let r = FieldElement::random(); + let r = CurveOrderElement::random(); let s = Temp { val: r.clone() }; let serialized = serde_json::to_string(&s); diff --git a/src/extension_field_gt.rs b/src/extension_field_gt.rs index 563586b..c9ce5a7 100644 --- a/src/extension_field_gt.rs +++ b/src/extension_field_gt.rs @@ -5,7 +5,7 @@ use super::ECCurve::fp4::FP4; use super::ECCurve::pair::{another, ate, ate2, fexp, initmp, miller}; use crate::constants::GROUP_GT_SIZE; use crate::errors::{SerzDeserzError, ValueError}; -use crate::field_elem::FieldElement; +use crate::curve_order_elem::CurveOrderElement; use crate::group_elem::GroupElement; use crate::group_elem_g1::G1; use crate::group_elem_g2::{parse_hex_as_fp2, G2}; @@ -96,7 +96,7 @@ impl GT { Self { value: m } } - pub fn pow(&self, e: &FieldElement) -> Self { + pub fn pow(&self, e: &CurveOrderElement) -> Self { Self { value: self.value.pow(&e.to_bignum()), } @@ -129,7 +129,7 @@ impl GT { self.value.clone() } - pub fn to_bytes(&self) -> Vec { + pub fn to_vec(&self) -> Vec { let mut temp = FP12::new(); temp.copy(&self.value); let mut bytes: [u8; GROUP_GT_SIZE] = [0; GROUP_GT_SIZE]; @@ -137,7 +137,7 @@ impl GT { bytes.to_vec() } - pub fn from_bytes(bytes: &[u8]) -> Result { + pub fn from_slice(bytes: &[u8]) -> Result { if bytes.len() != GROUP_GT_SIZE { return Err(SerzDeserzError::GTBytesIncorrectSize( bytes.len(), @@ -267,7 +267,7 @@ mod test { #[test] fn test_inverse() { - let minus_one = FieldElement::minus_one(); + let minus_one = CurveOrderElement::minus_one(); for _ in 0..10 { let g1 = G1::random(); let g2 = G2::random(); @@ -439,7 +439,7 @@ mod test { assert_eq!(rhs_2, rhs); assert_eq!(rhs_3, rhs); - let r = FieldElement::random(); + let r = CurveOrderElement::random(); // e(g1, g2^r) == e(g1^r, g2) == e(g1, g2)^r let p1 = GT::ate_pairing(&g1, &(&g2 * &r)); let p2 = GT::ate_pairing(&(&g1 * &r), &g2); @@ -490,8 +490,8 @@ mod test { let g1_vec = (0..count).map(|_| G1::random()).collect::>(); let g2_vec = (0..count).map(|_| G2::random()).collect::>(); let r_vec = (0..count) - .map(|_| FieldElement::random()) - .collect::>(); + .map(|_| CurveOrderElement::random()) + .collect::>(); //e(g1, g2)^r let mut pairing_exp = vec![]; diff --git a/src/group_elem.rs b/src/group_elem.rs index 999d7b8..01ca60f 100644 --- a/src/group_elem.rs +++ b/src/group_elem.rs @@ -1,8 +1,7 @@ use rand::{CryptoRng, RngCore}; use crate::errors::{SerzDeserzError, ValueError}; -use crate::field_elem::FieldElement; - +use crate::curve_order_elem::CurveOrderElement; use std::slice::Iter; #[macro_export] @@ -29,13 +28,13 @@ pub trait GroupElement: Clone + Sized { /// Return a random group element fn random() -> Self { - let n = FieldElement::random(); + let n = CurveOrderElement::random(); Self::generator().scalar_mul_const_time(&n) } /// Return a random group element using the given random number generator fn random_using_rng(rng: &mut R) -> Self { - let n = FieldElement::random_using_rng(rng); + let n = CurveOrderElement::random_using_rng(rng); Self::generator().scalar_mul_const_time(&n) } @@ -53,10 +52,10 @@ pub trait GroupElement: Clone + Sized { fn hash_to_curve(msg: &[u8], dst: &hash2curve::DomainSeparationTag) -> Self; /// Return byte representation as vector - fn to_bytes(&self) -> Vec; + fn to_vec(&self) -> Vec; /// Create an element from a byte representation - fn from_bytes(bytes: &[u8]) -> Result; + fn from_slice(bytes: &[u8]) -> Result; /// Writes bytes to given slice. Raises exception when given slice is not of desired length. fn write_to_slice(&self, target: &mut [u8]) -> Result<(), SerzDeserzError>; @@ -78,7 +77,7 @@ pub trait GroupElement: Clone + Sized { /// Multiply point on the curve (element of group G1) with a scalar. Constant time operation. /// self * field_element_a. - fn scalar_mul_const_time(&self, a: &FieldElement) -> Self; + fn scalar_mul_const_time(&self, a: &CurveOrderElement) -> Self; /// Return the double of the group element fn double(&self) -> Self; @@ -129,11 +128,17 @@ macro_rules! impl_group_elem_conversions { } } + impl From<[u8; $group_size]> for $group_element { + fn from(x: [u8; $group_size]) -> Self { + Self::from(&x) + } + } + impl Hash for $group_element { fn hash(&self, state: &mut H) { let mut bytes: [u8; $group_size] = [0; $group_size]; self.write_to_slice_unchecked(&mut bytes); - state.write(&self.to_bytes()) + state.write(&self.to_vec()) } } }; @@ -307,34 +312,34 @@ macro_rules! impl_group_elem_ops { } } - impl Mul for $group_element { + impl Mul for $group_element { type Output = Self; - fn mul(self, other: FieldElement) -> Self { + fn mul(self, other: CurveOrderElement) -> Self { self.scalar_mul_const_time(&other) } } - impl Mul<&FieldElement> for $group_element { + impl Mul<&CurveOrderElement> for $group_element { type Output = Self; - fn mul(self, other: &FieldElement) -> Self { + fn mul(self, other: &CurveOrderElement) -> Self { self.scalar_mul_const_time(other) } } - impl Mul for &$group_element { + impl Mul for &$group_element { type Output = $group_element; - fn mul(self, other: FieldElement) -> $group_element { + fn mul(self, other: CurveOrderElement) -> $group_element { self.scalar_mul_const_time(&other) } } - impl Mul<&FieldElement> for &$group_element { + impl Mul<&CurveOrderElement> for &$group_element { type Output = $group_element; - fn mul(self, other: &FieldElement) -> $group_element { + fn mul(self, other: &CurveOrderElement) -> $group_element { self.scalar_mul_const_time(other) } } @@ -363,7 +368,7 @@ macro_rules! impl_group_elem_ops { macro_rules! impl_scalar_mul_ops { ( $group_element:ident ) => { - impl Mul<$group_element> for FieldElement { + impl Mul<$group_element> for CurveOrderElement { type Output = $group_element; fn mul(self, other: $group_element) -> $group_element { @@ -371,7 +376,7 @@ macro_rules! impl_scalar_mul_ops { } } - impl Mul<&$group_element> for FieldElement { + impl Mul<&$group_element> for CurveOrderElement { type Output = $group_element; fn mul(self, other: &$group_element) -> $group_element { @@ -379,7 +384,7 @@ macro_rules! impl_scalar_mul_ops { } } - impl Mul<$group_element> for &FieldElement { + impl Mul<$group_element> for &CurveOrderElement { type Output = $group_element; fn mul(self, other: $group_element) -> $group_element { @@ -387,7 +392,7 @@ macro_rules! impl_scalar_mul_ops { } } - impl Mul<&$group_element> for &FieldElement { + impl Mul<&$group_element> for &CurveOrderElement { type Output = $group_element; fn mul(self, other: &$group_element) -> $group_element { @@ -445,7 +450,7 @@ macro_rules! impl_optmz_scalar_mul_ops { /// Multiply point on the curve (element of group G1) with a scalar. Variable time operation /// Uses wNAF. - pub fn scalar_mul_variable_time(&self, a: &FieldElement) -> Self { + pub fn scalar_mul_variable_time(&self, a: &CurveOrderElement) -> Self { // TODO: Optimization: Attach the lookup table to the struct let table = $lookup_table::from(self); let wnaf = a.to_wnaf(5); @@ -514,11 +519,11 @@ pub trait GroupElementVector: Sized { /// Multiply each element of the vector with a given field /// element `n` (scale the vector). Modifies the vector. - fn scale(&mut self, n: &FieldElement); + fn scale(&mut self, n: &CurveOrderElement); /// Multiply each element of the vector with a given field /// element `n` to create a new vector - fn scaled_by(&self, n: &FieldElement) -> Self; + fn scaled_by(&self, n: &CurveOrderElement) -> Self; /// Add 2 vectors fn plus(&self, b: &Self) -> Result; @@ -589,7 +594,7 @@ macro_rules! impl_group_elem_vec_ops { .reduce(|| $group_element::new(), |a, b| a + b) } - fn scale(&mut self, n: &FieldElement) { + fn scale(&mut self, n: &CurveOrderElement) { // TODO: Since each element is multiplied with same field element, use the // optimized version. for i in 0..self.len() { @@ -597,7 +602,7 @@ macro_rules! impl_group_elem_vec_ops { } } - fn scaled_by(&self, n: &FieldElement) -> Self { + fn scaled_by(&self, n: &CurveOrderElement) -> Self { // TODO: Since each element is multiplied with same field element, use the // optimized version. let mut scaled = Self::with_capacity(self.len()); @@ -651,14 +656,14 @@ macro_rules! impl_group_elem_vec_product_ops { /// [a1, a2, a3, ...field elements].[b1, b2, b3, ...group elements] = (a1*b1 + a2*b2 + a3*b3) pub fn inner_product_const_time<'g, 'f>( &'g self, - b: impl IntoIterator, + b: impl IntoIterator, ) -> Result<$group_element, ValueError> { self.multi_scalar_mul_const_time(b) } pub fn inner_product_var_time<'g, 'f>( &'g self, - b: impl IntoIterator, + b: impl IntoIterator, ) -> Result<$group_element, ValueError> { self.multi_scalar_mul_var_time(b) } @@ -666,7 +671,7 @@ macro_rules! impl_group_elem_vec_product_ops { #[deprecated(since = "0.3.0", note = "Please use the `inner_product_var_time` function instead")] pub fn inner_product_var_time_with_ref_vecs( group_elems: Vec<&$group_element>, - field_elems: Vec<&FieldElement>, + field_elems: Vec<&CurveOrderElement>, ) -> Result<$group_element, ValueError> { Self::multi_scalar_mul_var_time_without_precomputation(group_elems, field_elems) } @@ -692,7 +697,7 @@ macro_rules! impl_group_elem_vec_product_ops { /// multiplications and n-1 additions for `n` field elements pub fn multi_scalar_mul_const_time_naive( &self, - field_elems: &FieldElementVector, + field_elems: &CurveOrderElementVector, ) -> Result<$group_element, ValueError> { check_vector_size_for_equality!(field_elems, self)?; let mut accum = $group_element::new(); @@ -705,7 +710,7 @@ macro_rules! impl_group_elem_vec_product_ops { /// Constant time multi-scalar multiplication pub fn multi_scalar_mul_const_time<'g, 'f>( &'g self, - field_elems: impl IntoIterator, + field_elems: impl IntoIterator, ) -> Result<$group_element, ValueError> { Self::multi_scalar_mul_const_time_without_precomputation(self.as_slice(), field_elems) } @@ -713,7 +718,7 @@ macro_rules! impl_group_elem_vec_product_ops { /// Variable time multi-scalar multiplication pub fn multi_scalar_mul_var_time<'g, 'f>( &'g self, - field_elems: impl IntoIterator, + field_elems: impl IntoIterator, ) -> Result<$group_element, ValueError> { Self::multi_scalar_mul_var_time_without_precomputation(self.as_slice(), field_elems) } @@ -721,7 +726,7 @@ macro_rules! impl_group_elem_vec_product_ops { /// Strauss multi-scalar multiplication pub fn multi_scalar_mul_var_time_without_precomputation<'g, 'f>( group_elems: impl IntoIterator, - field_elems: impl IntoIterator, + field_elems: impl IntoIterator, ) -> Result<$group_element, ValueError> { let lookup_tables: Vec<_> = group_elems .into_iter() @@ -737,7 +742,7 @@ macro_rules! impl_group_elem_vec_product_ops { #[deprecated(since = "0.3.0", note = "Please use the `multi_scalar_mul_var_time_without_precomputation` function instead")] pub fn multi_scalar_mul_var_time_from_ref_vecs( group_elems: Vec<&$group_element>, - field_elems: Vec<&FieldElement>, + field_elems: Vec<&CurveOrderElement>, ) -> Result<$group_element, ValueError> { let lookup_tables: Vec<_> = group_elems .iter() @@ -753,7 +758,7 @@ macro_rules! impl_group_elem_vec_product_ops { /// Strauss multi-scalar multiplication. Passing the lookup tables since in lot of cases generators will be fixed pub fn multi_scalar_mul_var_time_with_precomputation_done<'f>( lookup_tables: &[$lookup_table], - field_elems: impl IntoIterator, + field_elems: impl IntoIterator, ) -> Result<$group_element, ValueError> { let mut nafs: Vec<_> = field_elems.into_iter().map(|e| e.to_wnaf(5)).collect(); @@ -785,7 +790,7 @@ macro_rules! impl_group_elem_vec_product_ops { /// Still helps with reducing doublings pub fn multi_scalar_mul_const_time_without_precomputation<'g, 'f>( group_elems: impl IntoIterator, - field_elems: impl IntoIterator, + field_elems: impl IntoIterator, ) -> Result<$group_element, ValueError> { // Choosing window of size 3. @@ -802,7 +807,7 @@ macro_rules! impl_group_elem_vec_product_ops { pub fn multi_scalar_mul_const_time_with_precomputation_done<'f>( group_elem_multiples: &[Vec<$group_element>], - field_elems: impl IntoIterator, + field_elems: impl IntoIterator, ) -> Result<$group_element, ValueError> { // TODO: The test shows that precomputing multiples does not help much. Experiment with bigger window. @@ -837,7 +842,7 @@ macro_rules! impl_group_elem_vec_product_ops { /// Non-constant time operation. Scale this group element vector by a factor. Each group /// element is multiplied by the same factor so wnaf is computed only once. - pub fn scale_var_time(&mut self, n: &FieldElement) { + pub fn scale_var_time(&mut self, n: &CurveOrderElement) { let wnaf = n.to_wnaf(5); self.elems.as_mut_slice().par_iter_mut().for_each(|e| { let table = $lookup_table::from(&(*e)); @@ -847,7 +852,7 @@ macro_rules! impl_group_elem_vec_product_ops { /// Non-constant time operation. Return a scaled vector. Each group /// element is multiplied by the same factor so wnaf is computed only once. - pub fn scaled_by_var_time(&self, n: &FieldElement) -> Self { + pub fn scaled_by_var_time(&self, n: &CurveOrderElement) -> Self { let mut scaled: Self = self.clone(); scaled.scale_var_time(n); scaled @@ -931,8 +936,9 @@ macro_rules! impl_group_elem_vec_conversions { #[cfg(test)] mod test { use super::*; + use serde::{Serialize, Deserialize}; use crate::constants::GROUP_G1_SIZE; - use crate::field_elem::FieldElementVector; + use crate::curve_order_elem::CurveOrderElementVector; #[cfg(any(feature = "bls381", feature = "bn254"))] use crate::constants::{GROUP_G2_SIZE, GROUP_GT_SIZE}; #[cfg(any(feature = "bls381", feature = "bn254"))] @@ -955,17 +961,17 @@ mod test { let y = $group::from(&bytes); assert_eq!(x, y); - let bytes1 = x.to_bytes(); - assert_eq!(x, $group::from_bytes(bytes1.as_slice()).unwrap()); + let bytes1 = x.to_vec(); + assert_eq!(x, $group::from_slice(bytes1.as_slice()).unwrap()); // Increase length of byte vector by adding a byte. Choice of byte is arbitrary let mut bytes2 = bytes1.clone(); bytes2.push(0); - assert!($group::from_bytes(&bytes2).is_err()); + assert!($group::from_slice(&bytes2).is_err()); assert!(x.write_to_slice(&mut bytes2).is_err()); // Decrease length of byte vector - assert!($group::from_bytes(&bytes2[0..$group_size - 4]).is_err()); + assert!($group::from_slice(&bytes2[0..$group_size - 4]).is_err()); assert!(x.write_to_slice(&mut bytes2[0..$group_size - 4]).is_err()); } }; @@ -1035,7 +1041,7 @@ mod test { ( $group:ident ) => { for _ in 0..10 { let g = $group::random(); - let f = FieldElement::random(); + let f = CurveOrderElement::random(); let m = g.scalar_mul_const_time(&f); // Operands can be in any order assert_eq!(m, &g * &f); @@ -1126,7 +1132,7 @@ mod test { } println!("Addition time for {} elems = {:?}", count, start.elapsed()); - let fs: Vec<_> = (0..100).map(|_| FieldElement::random()).collect(); + let fs: Vec<_> = (0..100).map(|_| CurveOrderElement::random()).collect(); start = Instant::now(); for i in 0..count { let _ = &points[i] * &fs[i]; @@ -1204,7 +1210,7 @@ mod test { let a = $group::random(); let table = $lookup_table::from(&a); for i in x.iter() { - let f = FieldElement::from(*i as u8); + let f = CurveOrderElement::from(*i as u8); let expected = &a * f; assert_eq!(expected, *table.select(*i as usize)); } @@ -1221,7 +1227,7 @@ mod test { ( $group:ident, $lookup_table:ident ) => { for _ in 0..100 { let a = $group::random(); - let r = FieldElement::random(); + let r = CurveOrderElement::random(); let expected = &a * &r; let table = $lookup_table::from(&a); @@ -1247,12 +1253,12 @@ mod test { let gen = $group::generator(); for i in 0..70 { - fs.push(FieldElement::random()); + fs.push(CurveOrderElement::random()); gs.push(gen.scalar_mul_const_time(&fs[i])); } let gv = $vector::from(gs.as_slice()); - let fv = FieldElementVector::from(fs.as_slice()); + let fv = CurveOrderElementVector::from(fs.as_slice()); let res = gv.multi_scalar_mul_const_time_naive(&fv).unwrap(); let res_1 = gv.multi_scalar_mul_var_time(fv.as_ref()).unwrap(); @@ -1294,7 +1300,7 @@ mod test { let size = 30; macro_rules! scale { ( $group_vec:ident ) => { - let r = FieldElement::random(); + let r = CurveOrderElement::random(); let vector = $group_vec::random(size); let start = Instant::now(); let s1 = vector.scaled_by(&r); diff --git a/src/group_elem_g1.rs b/src/group_elem_g1.rs index 2c8ef28..758e5f0 100644 --- a/src/group_elem_g1.rs +++ b/src/group_elem_g1.rs @@ -1,8 +1,8 @@ -use crate::constants::{CURVE_ORDER, GROUP_G1_SIZE}; +use crate::constants::{CURVE_ORDER, GROUP_G1_SIZE, FIELD_ORDER_ELEMENT_SIZE}; use crate::errors::{SerzDeserzError, ValueError}; -use crate::field_elem::{FieldElement, FieldElementVector}; +use crate::curve_order_elem::{CurveOrderElement, CurveOrderElementVector}; use crate::group_elem::{GroupElement, GroupElementVector}; -use crate::types::{GroupG1, FP}; +use crate::types::{GroupG1, FP, BigNum}; use crate::utils::hash_msg; use std::ops::{Add, AddAssign, Index, IndexMut, Mul, Neg, Sub, SubAssign}; @@ -10,10 +10,9 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::slice::Iter; -use crate::rayon::iter::IntoParallelRefMutIterator; use rayon::prelude::*; -use serde::de::{Deserialize, Deserializer, Error as DError, Visitor}; -use serde::ser::{Serialize, Serializer}; +use serde::de::{Error as DError, Visitor}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::str::{FromStr, SplitWhitespace}; use zeroize::Zeroize; use hash2curve::HashToCurveXmd; @@ -55,19 +54,21 @@ impl GroupElement for G1 { fn hash_to_curve(msg: &[u8], dst: &hash2curve::DomainSeparationTag) -> Self { let hasher = hash2curve::bls381g1::Bls12381G1Sswu::new(dst.clone()); - match hasher.hash_to_curve_xmd::(msg) { - Ok(p) => p.into(), + match hasher.hash_to_curve_xmd::(msg) { + Ok(p) => { + p.0.into() + }, Err(_) => Self::identity() } } - fn to_bytes(&self) -> Vec { + fn to_vec(&self) -> Vec { let mut bytes: [u8; GROUP_G1_SIZE] = [0; GROUP_G1_SIZE]; self.write_to_slice_unchecked(&mut bytes); bytes.to_vec() } - fn from_bytes(bytes: &[u8]) -> Result { + fn from_slice(bytes: &[u8]) -> Result { if bytes.len() != GROUP_G1_SIZE { return Err(SerzDeserzError::G1BytesIncorrectSize( bytes.len(), @@ -114,7 +115,7 @@ impl GroupElement for G1 { diff.into() } - fn scalar_mul_const_time(&self, a: &FieldElement) -> Self { + fn scalar_mul_const_time(&self, a: &CurveOrderElement) -> Self { self.value.mul(&a.to_bignum()).into() } @@ -163,11 +164,57 @@ impl G1 { /// Computes sum of 2 scalar multiplications. /// Faster than doing the scalar multiplications individually and then adding them. Uses lookup table /// returns self*a + h*b - pub fn binary_scalar_mul(&self, h: &Self, a: &FieldElement, b: &FieldElement) -> Self { + pub fn binary_scalar_mul(&self, h: &Self, a: &CurveOrderElement, b: &CurveOrderElement) -> Self { self.value .mul2(&a.to_bignum(), &h.to_ecp(), &b.to_bignum()) .into() } + + pub fn to_bytes(&self) -> [u8; 2 * FIELD_ORDER_ELEMENT_SIZE] { + let mut bytes = [0u8; FIELD_ORDER_ELEMENT_SIZE + 1]; + let mut temp = GroupG1::new(); + temp.copy(&self.value); + temp.tobytes(bytes.as_mut(), false); + *array_ref![bytes, 1, 2 * FIELD_ORDER_ELEMENT_SIZE] + } + + pub fn to_compressed_bytes(&self) -> [u8; FIELD_ORDER_ELEMENT_SIZE] { + let mut bytes = [0u8; FIELD_ORDER_ELEMENT_SIZE + 1]; + let mut temp = GroupG1::new(); + temp.copy(&self.value); + temp.tobytes(bytes.as_mut(), true); + bytes[1] |= (bytes[0] & 1) << 7; + *array_ref![bytes, 1, FIELD_ORDER_ELEMENT_SIZE] + } +} + +impl From<[u8; 2 * FIELD_ORDER_ELEMENT_SIZE]> for G1 { + fn from(data: [u8; 2 * FIELD_ORDER_ELEMENT_SIZE]) -> Self { + Self::from(&data) + } +} + +impl From<&[u8; 2 * FIELD_ORDER_ELEMENT_SIZE]> for G1 { + fn from(data: &[u8; 2 * FIELD_ORDER_ELEMENT_SIZE]) -> Self { + let x = BigNum::frombytes(&data[..FIELD_ORDER_ELEMENT_SIZE]); + let y = BigNum::frombytes(&data[FIELD_ORDER_ELEMENT_SIZE..]); + Self { value: GroupG1::new_bigs(&x, &y) } + } +} + +impl From<[u8; FIELD_ORDER_ELEMENT_SIZE]> for G1 { + fn from(data: [u8; FIELD_ORDER_ELEMENT_SIZE]) -> Self { + Self::from(&data) + } +} + +impl From<&[u8; FIELD_ORDER_ELEMENT_SIZE]> for G1 { + fn from(data: &[u8; FIELD_ORDER_ELEMENT_SIZE]) -> Self { + let parity = ((data[0] >> 7) & 1u8) as isize; + let mut temp = data.clone(); + temp[0] &= 0x7F; + Self { value: GroupG1::new_bigint(&BigNum::frombytes(&temp[..]), parity) } + } } impl_group_elem_traits!(G1, GroupG1); @@ -212,7 +259,7 @@ pub fn parse_hex_as_fp(iter: &mut SplitWhitespace) -> Result FieldElement::parse_hex_as_bignum(i.to_string())?, + Some(i) => CurveOrderElement::parse_hex_as_bignum(i.to_string())?, None => return Err(SerzDeserzError::CannotParseFP), }; @@ -226,9 +273,21 @@ mod test { use hash2curve::DomainSeparationTag; #[test] - fn test_hash_to_curve() { + fn compressed_tests() { + let g1 = G1::generator(); + let compressed_bytes = g1.to_compressed_bytes(); + let g1_1 = G1::from(compressed_bytes); + assert_eq!(g1, g1_1); let e = G1::from_hex("1 0546197CDBA187E858730894C66FAEB35E7DBE4C61646786FB85B3EBB78377B1711797A884CBE8302A23463FFFD00190 1 11CF30309EA1AF4BB47FC4D5219529347F9576201EE34DE933C96F83FBB8B2AC22387B593C5F148924B571FE605B337F 2 13317C30F3A0D636D56A23C34FDD80B891ECBDE7C2B7D6E16B0F4B0B7E6D26CB6147ACDE629C4A23C57400D203A9FB84".to_string()).unwrap(); - let dst = DomainSeparationTag::new("hash_to_curve_", Some("test"), None, None).unwrap(); + let compressed_bytes = e.to_compressed_bytes(); + let e1 = G1::from(compressed_bytes); + assert_eq!(e, e1); + } + + #[test] + fn test_hash_to_curve() { + let e = G1::from_hex("1 060595F69756F0528EAACAC84E6844CEBCB844042DC456EC738F7332221BF27CA38E6C3DC2FD8710FFE37ECB92779E46 1 153980BAF12F8EB31BBF9D8CACE7FB750AB76CEE4DD118CCB1A27637BE878544128ABDDA8F7E22A393B7920547BF6DEC 2 13317C30F3A0D636D56A23C34FDD80B891ECBDE7C2B7D6E16B0F4B0B7E6D26CB6147ACDE629C4A23C57400D203A9FB84".to_string()).unwrap(); + let dst = DomainSeparationTag::new(b"hash_to_curve_", Some(b"test"), None, None).unwrap(); let g = G1::hash_to_curve(b"message to be hashed", &dst); assert!(!g.is_identity()); assert_eq!(e, g); @@ -247,8 +306,8 @@ mod test { #[test] fn test_binary_scalar_mul() { for _ in 0..10 { - let a = FieldElement::random(); - let b = FieldElement::random(); + let a = CurveOrderElement::random(); + let b = CurveOrderElement::random(); let g = G1::random(); let h = G1::random(); assert_eq!(&g * &a + &h * &b, g.binary_scalar_mul(&h, &a, &b)) @@ -261,7 +320,7 @@ mod test { let a = G1::random(); let mults = a.get_multiples(17); for i in 1..=17 { - assert_eq!(mults[i - 1], (&a * FieldElement::from(i as u8))); + assert_eq!(mults[i - 1], (&a * CurveOrderElement::from(i as u8))); } } } @@ -274,12 +333,12 @@ mod test { let n = 64; for _ in 0..n { - fs.push(FieldElement::random()); + fs.push(CurveOrderElement::random()); gs.push(G1::random()); } let gv = G1Vector::from(gs.as_slice()); - let fv = FieldElementVector::from(fs.as_slice()); + let fv = CurveOrderElementVector::from(fs.as_slice()); let mut start = Instant::now(); let res = gv.multi_scalar_mul_const_time_naive(&fv).unwrap(); @@ -297,7 +356,7 @@ mod test { .map(|e| e.to_wnaf_lookup_table(5)) .collect(); - let f_refs: Vec<&FieldElement> = fs.iter().map(|f| f).collect(); + let f_refs: Vec<&CurveOrderElement> = fs.iter().map(|f| f).collect(); start = Instant::now(); let res_2 = G1Vector::multi_scalar_mul_var_time_with_precomputation_done(&lookup_tables, f_refs) @@ -359,12 +418,12 @@ mod test { let w = 5; for _ in 0..n { - fs.push(FieldElement::random()); + fs.push(CurveOrderElement::random()); gs.push(G1::random()); } let gv = G1Vector::from(gs.as_slice()); - let fv = FieldElementVector::from(fs.as_slice()); + let fv = CurveOrderElementVector::from(fs.as_slice()); let mut start = Instant::now(); for i in 0..n { diff --git a/src/group_elem_g2.rs b/src/group_elem_g2.rs index ef95a5a..22f0923 100644 --- a/src/group_elem_g2.rs +++ b/src/group_elem_g2.rs @@ -1,8 +1,8 @@ -use crate::constants::{CURVE_ORDER, GROUP_G2_SIZE}; +use crate::constants::{CURVE_ORDER, GROUP_G2_SIZE, FIELD_ORDER_ELEMENT_SIZE}; use crate::errors::{SerzDeserzError, ValueError}; -use crate::field_elem::{FieldElement, FieldElementVector}; +use crate::curve_order_elem::{CurveOrderElement, CurveOrderElementVector}; use crate::group_elem::{GroupElement, GroupElementVector}; -use crate::types::{GroupG2, FP2}; +use crate::types::{GroupG2, FP2, BigNum}; use crate::utils::hash_msg; use std::iter; use std::ops::{Add, AddAssign, Index, IndexMut, Mul, Neg, Sub, SubAssign}; @@ -12,10 +12,9 @@ use std::hash::{Hash, Hasher}; use std::slice::Iter; use crate::group_elem_g1::parse_hex_as_fp; -use crate::rayon::iter::IntoParallelRefMutIterator; use rayon::prelude::*; -use serde::de::{Deserialize, Deserializer, Error as DError, Visitor}; -use serde::ser::{Serialize, Serializer}; +use serde::{Serialize, Serializer, Deserialize, Deserializer}; +use serde::de::{Error as DError, Visitor}; use std::str::SplitWhitespace; use zeroize::Zeroize; @@ -59,13 +58,13 @@ impl GroupElement for G2 { unimplemented!(); } - fn to_bytes(&self) -> Vec { + fn to_vec(&self) -> Vec { let mut bytes: [u8; GROUP_G2_SIZE] = [0; GROUP_G2_SIZE]; self.write_to_slice_unchecked(&mut bytes); bytes.to_vec() } - fn from_bytes(bytes: &[u8]) -> Result { + fn from_slice(bytes: &[u8]) -> Result { if bytes.len() != GROUP_G2_SIZE { return Err(SerzDeserzError::G2BytesIncorrectSize( bytes.len(), @@ -112,7 +111,7 @@ impl GroupElement for G2 { diff.into() } - fn scalar_mul_const_time(&self, a: &FieldElement) -> Self { + fn scalar_mul_const_time(&self, a: &CurveOrderElement) -> Self { self.value.mul(&a.to_bignum()).into() } @@ -157,6 +156,67 @@ impl GroupElement for G2 { } } +impl G2 { + pub fn to_bytes(&self) -> [u8; 4 * FIELD_ORDER_ELEMENT_SIZE] { + let mut bytes = [0u8; 4 * FIELD_ORDER_ELEMENT_SIZE]; + self.value.tobytes(&mut bytes[..]); + bytes + } + + pub fn to_compressed_bytes(&self) -> [u8; 2 * FIELD_ORDER_ELEMENT_SIZE] { + let mut bytes = [0u8; 2 * FIELD_ORDER_ELEMENT_SIZE]; + let mut temp = GroupG2::new(); + temp.copy(&self.value); + temp.affine(); + + temp.x.geta().tobytes(&mut bytes[..FIELD_ORDER_ELEMENT_SIZE]); + temp.x.getb().tobytes(&mut bytes[FIELD_ORDER_ELEMENT_SIZE..]); + + let a = temp.y.geta().parity() as u8; + let b = temp.y.getb().parity() as u8; + + let parity = a << 1 | b; + bytes[0] |= parity << 6; + bytes + } +} + +impl From<[u8; 2*FIELD_ORDER_ELEMENT_SIZE]> for G2 { + fn from(data: [u8; 2*FIELD_ORDER_ELEMENT_SIZE]) -> Self { + Self::from(&data) + } +} + +impl From<&[u8; 2*FIELD_ORDER_ELEMENT_SIZE]> for G2 { + fn from(data: &[u8; 2*FIELD_ORDER_ELEMENT_SIZE]) -> Self { + let mut temp = data.clone(); + let parity = (temp[0] >> 6) & 3u8; + let pa = if parity & 2u8 == 2 { 1 } else { 0 }; + let pb = if parity & 1u8 == 1 { 1 } else { 0 }; + temp[0] &= 0x3F; + let mut a = BigNum::frombytes(&temp[..FIELD_ORDER_ELEMENT_SIZE]); + let mut b = BigNum::frombytes(&temp[FIELD_ORDER_ELEMENT_SIZE..]); + a.norm(); + b.norm(); + let mut x = FP2::new_bigs(&a, &b); + x.norm(); + + let mut y = GroupG2::rhs(&x); + if y.sqrt() { + if y.geta().parity() != pa { + y.a.neg(); + } + if y.getb().parity() != pb { + y.b.neg(); + } + y.reduce(); + } + + let g2 = GroupG2::new_fp2s(&x, &y); + Self { value: g2 } + } +} + /// Parse given hex string as FP2 pub fn parse_hex_as_fp2(iter: &mut SplitWhitespace) -> Result { // Logic almost copied from AMCL but with error handling and constant time execution. @@ -199,7 +259,7 @@ impl G2 { /// Computes sum of 2 scalar multiplications. /// Faster than doing the scalar multiplications individually and then adding them. Uses lookup table /// returns self*a + h*b - pub fn binary_scalar_mul(&self, h: &Self, a: &FieldElement, b: &FieldElement) -> Self { + pub fn binary_scalar_mul(&self, h: &Self, a: &CurveOrderElement, b: &CurveOrderElement) -> Self { // TODO: Replace with faster let group_elems = iter::once(self).chain(iter::once(h)); let field_elems = iter::once(a).chain(iter::once(b)); @@ -210,6 +270,26 @@ impl G2 { #[cfg(test)] mod test { + use super::G2; + use crate::group_elem::GroupElement; + use crate::curve_order_elem::CurveOrderElement; + + #[test] + fn test_compression() { + let g2 = G2::generator(); + let bytes = g2.to_compressed_bytes(); + assert_eq!(G2::from(bytes), g2); + + for _ in 0..30 { + let sk = CurveOrderElement::random(); + let pk = &g2 * &sk; + + let bytes = pk.to_compressed_bytes(); + let t = G2::from(bytes); + + assert_eq!(t, pk); + } + } #[test] fn test_parse_hex_for_fp2() { diff --git a/src/lib.rs b/src/lib.rs index 7524a55..0bb8dd2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,8 @@ pub extern crate amcl; #[macro_use] extern crate lazy_static; +#[macro_use] +extern crate arrayref; #[cfg(feature = "bn254")] pub use amcl::bn254 as ECCurve; @@ -18,20 +20,8 @@ pub use amcl::secp256k1 as ECCurve; #[cfg(feature = "ed25519")] pub use amcl::ed25519 as ECCurve; -extern crate serde; - -#[macro_use] -extern crate serde_derive; - -extern crate serde_json; - -extern crate rayon; - -extern crate subtle_encoding; - pub mod constants; pub mod types; -pub mod signum; #[macro_use] pub mod errors; @@ -42,7 +32,7 @@ pub mod macros; pub mod utils; #[macro_use] -pub mod field_elem; +pub mod curve_order_elem; #[macro_use] pub mod group_elem; #[macro_use] diff --git a/src/signum.rs b/src/signum.rs deleted file mode 100644 index 0f27327..0000000 --- a/src/signum.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::ops::BitXor; - -#[derive(Debug, Eq, PartialEq)] -pub enum Sgn0 { - /// Either 0 or positive - NonNegative, - /// Neither 0 nor positive - Negative -} - -impl BitXor for Sgn0 { - type Output = Self; - - fn bitxor(self, rhs: Self) -> Self { - if self == rhs { - Sgn0::NonNegative - } else { - Sgn0::Negative - } - } -} - diff --git a/src/univar_poly.rs b/src/univar_poly.rs index 2641c53..90d8c6c 100644 --- a/src/univar_poly.rs +++ b/src/univar_poly.rs @@ -1,55 +1,55 @@ use std::ops::{Add, Index, IndexMut, Mul, Sub}; -use crate::field_elem::{FieldElement, FieldElementVector}; -use crate::rayon::iter::IntoParallelRefIterator; +use crate::curve_order_elem::{CurveOrderElement, CurveOrderElementVector}; +use serde::{Deserialize, Serialize}; use rayon::prelude::*; use std::cmp::max; /// Univariate polynomial represented with coefficients in a vector. The ith element of the vector is the coefficient of the ith degree term. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] -pub struct UnivarPolynomial(pub FieldElementVector); +pub struct UnivarPolynomial(pub CurveOrderElementVector); impl UnivarPolynomial { /// Return a zero polynomial of degree `degree` pub fn new(degree: usize) -> Self { - let coeffs = FieldElementVector::new(degree + 1); + let coeffs = CurveOrderElementVector::new(degree + 1); UnivarPolynomial(coeffs) } /// Return a constant polynomial - pub fn new_constant(constant: FieldElement) -> Self { - let mut coeffs = FieldElementVector::new(1); + pub fn new_constant(constant: CurveOrderElement) -> Self { + let mut coeffs = CurveOrderElementVector::new(1); coeffs[0] = constant; UnivarPolynomial(coeffs) } /// Return a randomly chosen polynomial (each coefficient is randomly chosen) of degree `degree`. pub fn random(degree: usize) -> Self { - Self(FieldElementVector::random(degree + 1)) // +1 for constant term + Self(CurveOrderElementVector::random(degree + 1)) // +1 for constant term } /// Create a polynomial with given roots in `roots` /// i.e. (x-roots[0])*(x-roots[1])*(x-roots[2])...(x-roots[last]) given `roots` - pub fn new_with_roots(roots: &[FieldElement]) -> Self { + pub fn new_with_roots(roots: &[CurveOrderElement]) -> Self { // vector of [(x-roots[0]), (x-roots[1]), (x-roots[2]), ...] let x_i = roots .par_iter() .map(|i| { - let mut v = FieldElementVector::with_capacity(2); + let mut v = CurveOrderElementVector::with_capacity(2); v.push(-i); - v.push(FieldElement::one()); + v.push(CurveOrderElement::one()); UnivarPolynomial(v) }) .collect::>(); // Polynomial (x-roots[0])*(x-roots[1])*(x-roots[2])...(x-roots[last]) x_i.par_iter().cloned().reduce( - || Self::new_constant(FieldElement::one()), + || Self::new_constant(CurveOrderElement::one()), |a, b| UnivarPolynomial::multiply(&a, &b), ) } - pub fn coefficients(&self) -> &FieldElementVector { + pub fn coefficients(&self) -> &CurveOrderElementVector { &self.0 } @@ -70,7 +70,7 @@ impl UnivarPolynomial { } // Evaluate polynomial at given `x` - pub fn eval(&self, x: &FieldElement) -> FieldElement { + pub fn eval(&self, x: &CurveOrderElement) -> CurveOrderElement { if x.is_zero() { self[0].clone() } else { @@ -102,7 +102,7 @@ impl UnivarPolynomial { let div_degree = divisor.degree(); for i in (div_degree..=rem_degree).rev() { if remainder[i].is_zero() { - quotient.push(FieldElement::zero()); + quotient.push(CurveOrderElement::zero()); continue; } @@ -119,7 +119,7 @@ impl UnivarPolynomial { remainder.0.pop(); } ( - UnivarPolynomial(FieldElementVector::from(quotient)), + UnivarPolynomial(CurveOrderElementVector::from(quotient)), remainder, ) } @@ -151,7 +151,7 @@ impl UnivarPolynomial { let small_degree_terms = (0..=smaller_poly_degree) .into_par_iter() .map(|i| &sum_poly[i] + &smaller_poly[i]) - .collect::>(); + .collect::>(); // Replace small degree ([0, smaller_poly_degree]) terms in the sum_poly sum_poly.replace_small_degree_terms(smaller_poly_degree, small_degree_terms.into_iter()); sum_poly @@ -174,7 +174,7 @@ impl UnivarPolynomial { diff } - pub fn multiply_by_constant(&self, constant: &FieldElement) -> UnivarPolynomial { + pub fn multiply_by_constant(&self, constant: &CurveOrderElement) -> UnivarPolynomial { let mut new_poly = self.clone(); for i in 0..=self.degree() { new_poly[i] = constant * &self[i]; @@ -184,14 +184,14 @@ impl UnivarPolynomial { pub fn multiply_by_monic_monomial(&self, monomial_degree: u64) -> UnivarPolynomial { let mut new_poly = self.clone(); - let new_poly_beginning = FieldElementVector::new(monomial_degree as usize); + let new_poly_beginning = CurveOrderElementVector::new(monomial_degree as usize); new_poly.0.splice(0..0, new_poly_beginning); new_poly } /// Replace terms of `self` from degree 0 to `till_degree` with coefficients in `replace_with`. /// Assumes `replace_with` will yield at least `till_degree` + 1 coefficients - fn replace_small_degree_terms>( + fn replace_small_degree_terms>( &mut self, till_degree: usize, replace_with: I, @@ -201,15 +201,15 @@ impl UnivarPolynomial { } impl Index for UnivarPolynomial { - type Output = FieldElement; + type Output = CurveOrderElement; - fn index(&self, idx: usize) -> &FieldElement { + fn index(&self, idx: usize) -> &CurveOrderElement { &self.0[idx] } } impl IndexMut for UnivarPolynomial { - fn index_mut(&mut self, idx: usize) -> &mut FieldElement { + fn index_mut(&mut self, idx: usize) -> &mut CurveOrderElement { &mut self.0[idx] } } @@ -262,36 +262,36 @@ mod tests { #[test] fn test_poly() { let degree = 10; - let poly1 = UnivarPolynomial(FieldElementVector::random(degree + 1)); + let poly1 = UnivarPolynomial(CurveOrderElementVector::random(degree + 1)); assert!(!poly1.is_zero()); - let poly2 = UnivarPolynomial(FieldElementVector::new(degree + 1)); + let poly2 = UnivarPolynomial(CurveOrderElementVector::new(degree + 1)); assert!(poly2.is_zero()); let poly3 = UnivarPolynomial::new(degree); assert!(poly3.is_zero()); - let poly4 = UnivarPolynomial::new_constant(FieldElement::from(100u64)); + let poly4 = UnivarPolynomial::new_constant(CurveOrderElement::from(100u64)); assert!(!poly4.is_zero()); assert_eq!(poly4.degree(), 0); - assert_eq!(poly4[0], FieldElement::from(100u64)); + assert_eq!(poly4[0], CurveOrderElement::from(100u64)); } #[test] fn test_create_poly_from_macro() { let poly = univar_polynomial!( - FieldElement::one(), - FieldElement::zero(), - FieldElement::from(87u64), - -FieldElement::one(), - FieldElement::from(300u64) + CurveOrderElement::one(), + CurveOrderElement::zero(), + CurveOrderElement::from(87u64), + -CurveOrderElement::one(), + CurveOrderElement::from(300u64) ); assert_eq!(poly.degree(), 4); - assert_eq!(poly[0], FieldElement::one()); - assert_eq!(poly[1], FieldElement::zero()); - assert_eq!(poly[2], FieldElement::from(87u64)); - assert_eq!(poly[3], FieldElement::minus_one()); - assert_eq!(poly[4], FieldElement::from(300u64)); + assert_eq!(poly[0], CurveOrderElement::one()); + assert_eq!(poly[1], CurveOrderElement::zero()); + assert_eq!(poly[2], CurveOrderElement::from(87u64)); + assert_eq!(poly[3], CurveOrderElement::minus_one()); + assert_eq!(poly[4], CurveOrderElement::from(300u64)); } #[test] @@ -299,20 +299,20 @@ mod tests { // x^2 - 1 / x + 1 = x - 1 // dividend = -1 + x^2 let c1 = vec![ - FieldElement::minus_one(), - FieldElement::zero(), - FieldElement::one(), + CurveOrderElement::minus_one(), + CurveOrderElement::zero(), + CurveOrderElement::one(), ]; - let dividend = UnivarPolynomial(FieldElementVector::from(c1)); + let dividend = UnivarPolynomial(CurveOrderElementVector::from(c1)); // divisor = 1 + x - let c2 = vec![FieldElement::one(), FieldElement::one()]; - let divisor = UnivarPolynomial(FieldElementVector::from(c2)); + let c2 = vec![CurveOrderElement::one(), CurveOrderElement::one()]; + let divisor = UnivarPolynomial(CurveOrderElementVector::from(c2)); let (quotient, rem) = UnivarPolynomial::long_division(÷nd, &divisor); println!("Quotient={:?}", "ient); // quotient = -1 + x assert_eq!(quotient.degree(), 1); - assert_eq!(quotient[0], FieldElement::minus_one()); - assert_eq!(quotient[1], FieldElement::one()); + assert_eq!(quotient[0], CurveOrderElement::minus_one()); + assert_eq!(quotient[1], CurveOrderElement::one()); assert_eq!(rem.degree(), 0); @@ -320,97 +320,97 @@ mod tests { println!("Quotient={:?}", "ient); // quotient = 1 + x assert_eq!(quotient.degree(), 1); - assert_eq!(quotient[0], FieldElement::one()); - assert_eq!(quotient[1], FieldElement::one()); + assert_eq!(quotient[0], CurveOrderElement::one()); + assert_eq!(quotient[1], CurveOrderElement::one()); // 2x^2 + 3x + 1 / x + 1 = 2x + 1 // dividend = 1 + 3x + 2x^2 let c1 = vec![ - FieldElement::one(), - FieldElement::from(3u64), - FieldElement::from(2u64), + CurveOrderElement::one(), + CurveOrderElement::from(3u64), + CurveOrderElement::from(2u64), ]; - let dividend = UnivarPolynomial(FieldElementVector::from(c1)); + let dividend = UnivarPolynomial(CurveOrderElementVector::from(c1)); // divisor = 1 + x - let c2 = vec![FieldElement::one(), FieldElement::one()]; - let divisor = UnivarPolynomial(FieldElementVector::from(c2)); + let c2 = vec![CurveOrderElement::one(), CurveOrderElement::one()]; + let divisor = UnivarPolynomial(CurveOrderElementVector::from(c2)); let (quotient, rem) = UnivarPolynomial::long_division(÷nd, &divisor); println!("Quotient={:?}", "ient); // quotient = 1 + 2x assert_eq!(quotient.degree(), 1); - assert_eq!(quotient[0], FieldElement::one()); - assert_eq!(quotient[1], FieldElement::from(2u64)); + assert_eq!(quotient[0], CurveOrderElement::one()); + assert_eq!(quotient[1], CurveOrderElement::from(2u64)); assert_eq!(rem.degree(), 0); // 4x - 4 / x - 1 = 4 // dividend = -4 + 4x - let c1 = vec![-FieldElement::from(4u64), FieldElement::from(4u64)]; - let dividend = UnivarPolynomial(FieldElementVector::from(c1)); + let c1 = vec![-CurveOrderElement::from(4u64), CurveOrderElement::from(4u64)]; + let dividend = UnivarPolynomial(CurveOrderElementVector::from(c1)); // divisor = -1 + x - let c2 = vec![FieldElement::minus_one(), FieldElement::one()]; - let divisor = UnivarPolynomial(FieldElementVector::from(c2)); + let c2 = vec![CurveOrderElement::minus_one(), CurveOrderElement::one()]; + let divisor = UnivarPolynomial(CurveOrderElementVector::from(c2)); let (quotient, rem) = UnivarPolynomial::long_division(÷nd, &divisor); println!("Quotient={:?}", "ient); // quotient = 4 assert_eq!(quotient.degree(), 0); - assert_eq!(quotient[0], FieldElement::from(4u64)); + assert_eq!(quotient[0], CurveOrderElement::from(4u64)); assert_eq!(rem.degree(), 0); // x^5 + x^3 + 4x^2 + 4 / x^2 + 1 = x^3 + 4 // dividend = 4 + 4x^2 + x^3 + x^5 let c1 = vec![ - FieldElement::from(4u64), - FieldElement::zero(), - FieldElement::from(4u64), - FieldElement::one(), - FieldElement::zero(), - FieldElement::one(), + CurveOrderElement::from(4u64), + CurveOrderElement::zero(), + CurveOrderElement::from(4u64), + CurveOrderElement::one(), + CurveOrderElement::zero(), + CurveOrderElement::one(), ]; - let dividend = UnivarPolynomial(FieldElementVector::from(c1)); + let dividend = UnivarPolynomial(CurveOrderElementVector::from(c1)); // divisor = 1 + x^2 let c2 = vec![ - FieldElement::one(), - FieldElement::zero(), - FieldElement::one(), + CurveOrderElement::one(), + CurveOrderElement::zero(), + CurveOrderElement::one(), ]; - let divisor = UnivarPolynomial(FieldElementVector::from(c2)); + let divisor = UnivarPolynomial(CurveOrderElementVector::from(c2)); let (quotient, rem) = UnivarPolynomial::long_division(÷nd, &divisor); println!("Quotient={:?}", "ient); // quotient = 4 + x^3 assert_eq!(quotient.degree(), 3); - assert_eq!(quotient[0], FieldElement::from(4u64)); - assert_eq!(quotient[1], FieldElement::zero()); - assert_eq!(quotient[2], FieldElement::zero()); - assert_eq!(quotient[3], FieldElement::one()); + assert_eq!(quotient[0], CurveOrderElement::from(4u64)); + assert_eq!(quotient[1], CurveOrderElement::zero()); + assert_eq!(quotient[2], CurveOrderElement::zero()); + assert_eq!(quotient[3], CurveOrderElement::one()); assert_eq!(rem.degree(), 1); // 2x^4 - 40x^3 + 3x^2 - 56x - 80 / x - 20 = 2x^3 + 3x + 4 // dividend = -80 - 56x + 3x^2 - 40x^3 + 2x^4 let c1 = vec![ - -FieldElement::from(80u64), - -FieldElement::from(56u64), - FieldElement::from(3u64), - -FieldElement::from(40u64), - FieldElement::from(2u64), + -CurveOrderElement::from(80u64), + -CurveOrderElement::from(56u64), + CurveOrderElement::from(3u64), + -CurveOrderElement::from(40u64), + CurveOrderElement::from(2u64), ]; - let dividend = UnivarPolynomial(FieldElementVector::from(c1)); + let dividend = UnivarPolynomial(CurveOrderElementVector::from(c1)); // divisor = -20 + x - let c2 = vec![-FieldElement::from(20), FieldElement::one()]; - let divisor = UnivarPolynomial(FieldElementVector::from(c2)); + let c2 = vec![-CurveOrderElement::from(20), CurveOrderElement::one()]; + let divisor = UnivarPolynomial(CurveOrderElementVector::from(c2)); let (quotient, rem) = UnivarPolynomial::long_division(÷nd, &divisor); println!("Quotient={:?}", "ient); // quotient = 4 + 3x + 2x^3 assert_eq!(quotient.degree(), 3); - assert_eq!(quotient[0], FieldElement::from(4u64)); - assert_eq!(quotient[1], FieldElement::from(3u64)); - assert_eq!(quotient[2], FieldElement::zero()); - assert_eq!(quotient[3], FieldElement::from(2u64)); + assert_eq!(quotient[0], CurveOrderElement::from(4u64)); + assert_eq!(quotient[1], CurveOrderElement::from(3u64)); + assert_eq!(quotient[2], CurveOrderElement::zero()); + assert_eq!(quotient[3], CurveOrderElement::from(2u64)); assert_eq!(rem.degree(), 0); } @@ -419,69 +419,69 @@ mod tests { fn test_poly_multiply() { // (x + 1) * (x - 1) = x^2 - 1 // x + 1 - let left = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::one(), - FieldElement::one(), + let left = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::one(), + CurveOrderElement::one(), ])); // -1 + x - let right = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::minus_one(), - FieldElement::one(), + let right = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::minus_one(), + CurveOrderElement::one(), ])); let product = UnivarPolynomial::multiply(&left, &right); // product = -1 + x^2 assert_eq!(product.degree(), 2); - assert_eq!(product[0], FieldElement::minus_one()); - assert_eq!(product[1], FieldElement::zero()); - assert_eq!(product[2], FieldElement::one()); + assert_eq!(product[0], CurveOrderElement::minus_one()); + assert_eq!(product[1], CurveOrderElement::zero()); + assert_eq!(product[2], CurveOrderElement::one()); // Test overloaded operator assert_eq!(product, &left * &right); // (x + 1) * (2x + 1) = 2x^2 + 3x + 1 // 1 + x - let left = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::one(), - FieldElement::one(), + let left = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::one(), + CurveOrderElement::one(), ])); // 1 + 2x - let right = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::one(), - FieldElement::from(2u64), + let right = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::one(), + CurveOrderElement::from(2u64), ])); let product = UnivarPolynomial::multiply(&left, &right); // product = 2x^2 + 3x + 1 assert_eq!(product.degree(), 2); - assert_eq!(product[0], FieldElement::one()); - assert_eq!(product[1], FieldElement::from(3u64)); - assert_eq!(product[2], FieldElement::from(2u64)); + assert_eq!(product[0], CurveOrderElement::one()); + assert_eq!(product[1], CurveOrderElement::from(3u64)); + assert_eq!(product[2], CurveOrderElement::from(2u64)); // Test overloaded operator assert_eq!(product, &left * &right); // (x^2 + 1) * (x^3 + 4) = x^5 + x^3 + 4x^2 + 4 // 1 + x^2 - let left = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::one(), - FieldElement::zero(), - FieldElement::one(), + let left = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::one(), + CurveOrderElement::zero(), + CurveOrderElement::one(), ])); // 4 + x^3 - let right = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::from(4u64), - FieldElement::zero(), - FieldElement::zero(), - FieldElement::one(), + let right = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::from(4u64), + CurveOrderElement::zero(), + CurveOrderElement::zero(), + CurveOrderElement::one(), ])); let product = UnivarPolynomial::multiply(&left, &right); // 4 + 4x^2 + x^3 + x^5 assert_eq!(product.degree(), 5); - assert_eq!(product[0], FieldElement::from(4u64)); - assert_eq!(product[1], FieldElement::zero()); - assert_eq!(product[2], FieldElement::from(4u64)); - assert_eq!(product[3], FieldElement::one()); - assert_eq!(product[4], FieldElement::zero()); - assert_eq!(product[5], FieldElement::one()); + assert_eq!(product[0], CurveOrderElement::from(4u64)); + assert_eq!(product[1], CurveOrderElement::zero()); + assert_eq!(product[2], CurveOrderElement::from(4u64)); + assert_eq!(product[3], CurveOrderElement::one()); + assert_eq!(product[4], CurveOrderElement::zero()); + assert_eq!(product[5], CurveOrderElement::one()); // Test overloaded operator assert_eq!(product, &left * &right); @@ -492,54 +492,54 @@ mod tests { // x^2 - 5 / x + 1 => q = x - 1, r = -4 // dividend = -5 + x^2 let c1 = vec![ - -FieldElement::from(5u64), - FieldElement::zero(), - FieldElement::one(), + -CurveOrderElement::from(5u64), + CurveOrderElement::zero(), + CurveOrderElement::one(), ]; - let dividend = UnivarPolynomial(FieldElementVector::from(c1)); + let dividend = UnivarPolynomial(CurveOrderElementVector::from(c1)); // divisor = 1 + x - let c2 = vec![FieldElement::one(), FieldElement::one()]; - let divisor = UnivarPolynomial(FieldElementVector::from(c2)); + let c2 = vec![CurveOrderElement::one(), CurveOrderElement::one()]; + let divisor = UnivarPolynomial(CurveOrderElementVector::from(c2)); let (quotient, remainder) = UnivarPolynomial::long_division(÷nd, &divisor); // quotient = -1 + x assert_eq!(quotient.degree(), 1); - assert_eq!(quotient[0], FieldElement::minus_one()); - assert_eq!(quotient[1], FieldElement::one()); + assert_eq!(quotient[0], CurveOrderElement::minus_one()); + assert_eq!(quotient[1], CurveOrderElement::one()); // remainder = -4 assert_eq!(remainder.degree(), 0); - assert_eq!(remainder[0], -FieldElement::from(4u64)); + assert_eq!(remainder[0], -CurveOrderElement::from(4u64)); // x^5 + 2x^3 + 4x^2 + 4 / x^2 + 1 = q = x^3 + x + 4, r = -x // dividend = 4 + 4x^2 + 2x^3 + x^5 let c1 = vec![ - FieldElement::from(4u64), - FieldElement::zero(), - FieldElement::from(4u64), - FieldElement::from(2u64), - FieldElement::zero(), - FieldElement::one(), + CurveOrderElement::from(4u64), + CurveOrderElement::zero(), + CurveOrderElement::from(4u64), + CurveOrderElement::from(2u64), + CurveOrderElement::zero(), + CurveOrderElement::one(), ]; - let dividend = UnivarPolynomial(FieldElementVector::from(c1)); + let dividend = UnivarPolynomial(CurveOrderElementVector::from(c1)); // divisor = 1 + x^2 let c2 = vec![ - FieldElement::one(), - FieldElement::zero(), - FieldElement::one(), + CurveOrderElement::one(), + CurveOrderElement::zero(), + CurveOrderElement::one(), ]; - let divisor = UnivarPolynomial(FieldElementVector::from(c2)); + let divisor = UnivarPolynomial(CurveOrderElementVector::from(c2)); let (quotient, remainder) = UnivarPolynomial::long_division(÷nd, &divisor); // quotient = 4 + x^3 assert_eq!(quotient.degree(), 3); - assert_eq!(quotient[0], FieldElement::from(4u64)); - assert_eq!(quotient[1], FieldElement::one()); - assert_eq!(quotient[2], FieldElement::zero()); - assert_eq!(quotient[3], FieldElement::one()); + assert_eq!(quotient[0], CurveOrderElement::from(4u64)); + assert_eq!(quotient[1], CurveOrderElement::one()); + assert_eq!(quotient[2], CurveOrderElement::zero()); + assert_eq!(quotient[3], CurveOrderElement::one()); assert_eq!(remainder.degree(), 1); - assert_eq!(remainder[0], FieldElement::zero()); - assert_eq!(remainder[1], FieldElement::minus_one()); + assert_eq!(remainder[0], CurveOrderElement::zero()); + assert_eq!(remainder[1], CurveOrderElement::minus_one()); } #[test] @@ -654,11 +654,11 @@ mod tests { let start = Instant::now(); for _ in 0..num_test_cases { let num_roots = rng.gen_range(2, 30); - let roots = FieldElementVector::random(num_roots); + let roots = CurveOrderElementVector::random(num_roots); let poly = UnivarPolynomial::new_with_roots(roots.as_slice()); assert_eq!(poly.degree(), num_roots); for r in roots { - assert_eq!(poly.eval(&r), FieldElement::zero()) + assert_eq!(poly.eval(&r), CurveOrderElement::zero()) } } println!("Time for {} elems = {:?}", num_test_cases, start.elapsed()); @@ -667,45 +667,45 @@ mod tests { #[test] fn test_multiply_with_constant() { // 9 + 2x + 75x^2 + 128x^3 - let orig = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::from(9u64), - FieldElement::from(2u64), - FieldElement::from(75u64), - FieldElement::from(128u64), + let orig = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::from(9u64), + CurveOrderElement::from(2u64), + CurveOrderElement::from(75u64), + CurveOrderElement::from(128u64), ])); - let c = FieldElement::from(3u64); + let c = CurveOrderElement::from(3u64); let new = orig.multiply_by_constant(&c); assert_eq!(new.degree(), 3); - assert_eq!(new[0], FieldElement::from(27)); - assert_eq!(new[1], FieldElement::from(6)); - assert_eq!(new[2], FieldElement::from(225)); - assert_eq!(new[3], FieldElement::from(384)); + assert_eq!(new[0], CurveOrderElement::from(27)); + assert_eq!(new[1], CurveOrderElement::from(6)); + assert_eq!(new[2], CurveOrderElement::from(225)); + assert_eq!(new[3], CurveOrderElement::from(384)); // 1 + 4x^2 + 5x^3 + 18x^6 - let orig = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::one(), - FieldElement::zero(), - FieldElement::from(4u64), - FieldElement::from(5u64), - FieldElement::zero(), - FieldElement::zero(), - FieldElement::from(18u64), + let orig = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::one(), + CurveOrderElement::zero(), + CurveOrderElement::from(4u64), + CurveOrderElement::from(5u64), + CurveOrderElement::zero(), + CurveOrderElement::zero(), + CurveOrderElement::from(18u64), ])); - let c = FieldElement::from(10u64); + let c = CurveOrderElement::from(10u64); let new = orig.multiply_by_constant(&c); assert_eq!(new.degree(), 6); - assert_eq!(new[0], FieldElement::from(10)); - assert_eq!(new[1], FieldElement::zero()); - assert_eq!(new[2], FieldElement::from(40)); - assert_eq!(new[3], FieldElement::from(50)); - assert_eq!(new[4], FieldElement::zero()); - assert_eq!(new[5], FieldElement::zero()); - assert_eq!(new[6], FieldElement::from(180)); + assert_eq!(new[0], CurveOrderElement::from(10)); + assert_eq!(new[1], CurveOrderElement::zero()); + assert_eq!(new[2], CurveOrderElement::from(40)); + assert_eq!(new[3], CurveOrderElement::from(50)); + assert_eq!(new[4], CurveOrderElement::zero()); + assert_eq!(new[5], CurveOrderElement::zero()); + assert_eq!(new[6], CurveOrderElement::from(180)); // take a random polynomial, multiply it with a constant, then multiply it with inverse of // the same constant. result should be same as original let random_poly = UnivarPolynomial::random(10); - let c = FieldElement::random(); + let c = CurveOrderElement::random(); let c_inv = c.inverse(); assert_eq!( random_poly, @@ -718,11 +718,11 @@ mod tests { #[test] fn test_multiply_with_monic_monomial() { // 9 + 2x + 75x^2 + 128x^3 - let orig = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::from(9u64), - FieldElement::from(2u64), - FieldElement::from(75u64), - FieldElement::from(128u64), + let orig = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::from(9u64), + CurveOrderElement::from(2u64), + CurveOrderElement::from(75u64), + CurveOrderElement::from(128u64), ])); let monomial_degree = 0; @@ -732,31 +732,31 @@ mod tests { let monomial_degree = 1; let new = orig.multiply_by_monic_monomial(monomial_degree); assert_eq!(new.degree(), 4); - assert_eq!(new[0], FieldElement::zero()); - assert_eq!(new[1], FieldElement::from(9u64)); - assert_eq!(new[2], FieldElement::from(2u64)); - assert_eq!(new[3], FieldElement::from(75u64)); - assert_eq!(new[4], FieldElement::from(128u64)); + assert_eq!(new[0], CurveOrderElement::zero()); + assert_eq!(new[1], CurveOrderElement::from(9u64)); + assert_eq!(new[2], CurveOrderElement::from(2u64)); + assert_eq!(new[3], CurveOrderElement::from(75u64)); + assert_eq!(new[4], CurveOrderElement::from(128u64)); let monomial_degree = 2; let new = orig.multiply_by_monic_monomial(monomial_degree); assert_eq!(new.degree(), 5); - assert_eq!(new[0], FieldElement::zero()); - assert_eq!(new[1], FieldElement::zero()); - assert_eq!(new[2], FieldElement::from(9u64)); - assert_eq!(new[3], FieldElement::from(2u64)); - assert_eq!(new[4], FieldElement::from(75u64)); - assert_eq!(new[5], FieldElement::from(128u64)); + assert_eq!(new[0], CurveOrderElement::zero()); + assert_eq!(new[1], CurveOrderElement::zero()); + assert_eq!(new[2], CurveOrderElement::from(9u64)); + assert_eq!(new[3], CurveOrderElement::from(2u64)); + assert_eq!(new[4], CurveOrderElement::from(75u64)); + assert_eq!(new[5], CurveOrderElement::from(128u64)); // 1 + 4x^2 + 5x^3 + 18x^6 - let orig = UnivarPolynomial(FieldElementVector::from(vec![ - FieldElement::one(), - FieldElement::zero(), - FieldElement::from(4u64), - FieldElement::from(5u64), - FieldElement::zero(), - FieldElement::zero(), - FieldElement::from(18u64), + let orig = UnivarPolynomial(CurveOrderElementVector::from(vec![ + CurveOrderElement::one(), + CurveOrderElement::zero(), + CurveOrderElement::from(4u64), + CurveOrderElement::from(5u64), + CurveOrderElement::zero(), + CurveOrderElement::zero(), + CurveOrderElement::from(18u64), ])); let monomial_degree = 0; @@ -766,26 +766,26 @@ mod tests { let monomial_degree = 1; let new = orig.multiply_by_monic_monomial(monomial_degree); assert_eq!(new.degree(), 7); - assert_eq!(new[0], FieldElement::zero()); - assert_eq!(new[1], FieldElement::one()); - assert_eq!(new[2], FieldElement::zero()); - assert_eq!(new[3], FieldElement::from(4)); - assert_eq!(new[4], FieldElement::from(5)); - assert_eq!(new[5], FieldElement::zero()); - assert_eq!(new[6], FieldElement::zero()); - assert_eq!(new[7], FieldElement::from(18)); + assert_eq!(new[0], CurveOrderElement::zero()); + assert_eq!(new[1], CurveOrderElement::one()); + assert_eq!(new[2], CurveOrderElement::zero()); + assert_eq!(new[3], CurveOrderElement::from(4)); + assert_eq!(new[4], CurveOrderElement::from(5)); + assert_eq!(new[5], CurveOrderElement::zero()); + assert_eq!(new[6], CurveOrderElement::zero()); + assert_eq!(new[7], CurveOrderElement::from(18)); let monomial_degree = 2; let new = orig.multiply_by_monic_monomial(monomial_degree); assert_eq!(new.degree(), 8); - assert_eq!(new[0], FieldElement::zero()); - assert_eq!(new[1], FieldElement::zero()); - assert_eq!(new[2], FieldElement::one()); - assert_eq!(new[3], FieldElement::zero()); - assert_eq!(new[4], FieldElement::from(4)); - assert_eq!(new[5], FieldElement::from(5)); - assert_eq!(new[6], FieldElement::zero()); - assert_eq!(new[7], FieldElement::zero()); - assert_eq!(new[8], FieldElement::from(18)); + assert_eq!(new[0], CurveOrderElement::zero()); + assert_eq!(new[1], CurveOrderElement::zero()); + assert_eq!(new[2], CurveOrderElement::one()); + assert_eq!(new[3], CurveOrderElement::zero()); + assert_eq!(new[4], CurveOrderElement::from(4)); + assert_eq!(new[5], CurveOrderElement::from(5)); + assert_eq!(new[6], CurveOrderElement::zero()); + assert_eq!(new[7], CurveOrderElement::zero()); + assert_eq!(new[8], CurveOrderElement::from(18)); } } diff --git a/src/utils.rs b/src/utils.rs index 57b681a..7bf6a42 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -3,7 +3,7 @@ extern crate sha3; use rand::{CryptoRng, RngCore}; -use crate::constants::{CURVE_ORDER, FIELD_ELEMENT_SIZE}; +use crate::constants::{CURVE_ORDER, FIELD_ORDER_ELEMENT_SIZE}; use crate::types::{BigNum, DoubleBigNum}; use amcl::rand::RAND; @@ -11,10 +11,10 @@ use sha3::digest::{ExtendableOutput, Input, XofReader}; use sha3::Shake256; /// Hash message and return output of size equal to curve modulus. Uses SHAKE to hash the message. -pub fn hash_msg(msg: &[u8]) -> [u8; FIELD_ELEMENT_SIZE] { +pub fn hash_msg(msg: &[u8]) -> [u8; FIELD_ORDER_ELEMENT_SIZE] { let mut hasher = Shake256::default(); hasher.input(&msg); - let mut h: [u8; FIELD_ELEMENT_SIZE] = [0; FIELD_ELEMENT_SIZE]; + let mut h = [0u8; FIELD_ORDER_ELEMENT_SIZE]; hasher.xof_result().read(&mut h); h } @@ -160,7 +160,7 @@ pub fn barrett_reduction_params(modulus: &BigNum) -> (usize, BigNum, BigNum) { mod test { use super::*; use crate::constants; - use crate::field_elem::FieldElement; + use crate::curve_order_elem::CurveOrderElement; use crate::group_elem::GroupElement; use crate::group_elem_g1::G1; use crate::utils::rand::Rng; @@ -173,7 +173,7 @@ mod test { fn timing_fp_big() { // TODO: Compare adding raw BIGs and FieldElement to check the overhead of the abstraction let count = 100; - let elems: Vec<_> = (0..count).map(|_| FieldElement::random()).collect(); + let elems: Vec<_> = (0..count).map(|_| CurveOrderElement::random()).collect(); let bigs: Vec<_> = elems.iter().map(|f| f.to_bignum()).collect(); let fs: Vec<_> = bigs.iter().map(|b| FP::new_big(&b)).collect(); let mut res_mul = BIG::new_int(1 as isize); @@ -198,7 +198,7 @@ mod test { start.elapsed() ); - let res_mul = FieldElement::one(); + let res_mul = CurveOrderElement::one(); start = Instant::now(); for e in &elems { res_mul.multiply(&e); @@ -267,8 +267,8 @@ mod test { let mut r2 = vec![]; for _ in 0..count { - a.push(FieldElement::random().to_bignum()); - b.push(FieldElement::random().to_bignum()); + a.push(CurveOrderElement::random().to_bignum()); + b.push(CurveOrderElement::random().to_bignum()); let mut x: G1 = GroupElement::random(); g.push(x.to_ecp()); x = GroupElement::random(); @@ -342,7 +342,7 @@ mod test { *constants::BARRETT_REDC_V, ); let count = 100; - let elems: Vec<_> = (0..count).map(|_| FieldElement::random()).collect(); + let elems: Vec<_> = (0..count).map(|_| CurveOrderElement::random()).collect(); let bigs: Vec<_> = elems.iter().map(|f| f.to_bignum()).collect(); let mut sum = bigs[0].clone(); From 421f81f850fea4669f860d3471d6eb69912002b1 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Tue, 21 Apr 2020 14:27:11 -0600 Subject: [PATCH 13/15] Update to fix other curves Signed-off-by: Michael Lodder --- src/constants.rs | 6 +++--- src/curve_order_elem.rs | 2 ++ src/group_elem_g1.rs | 6 ++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 57c8b40..fbac943 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -12,11 +12,11 @@ pub const FIELD_ORDER_ELEMENT_SIZE: usize = MODBYTES; #[cfg(feature = "bls381")] pub const CURVE_ORDER_ELEMENT_SIZE: usize = 32; #[cfg(feature = "bn254")] -pub const CURVE_ORDER_ELEMENT_SIZE: usize = 28; +pub const CURVE_ORDER_ELEMENT_SIZE: usize = 32; #[cfg(feature = "secp256k1")] -pub const CURVE_ORDER_ELEMENT_SIZE: usize = 28; +pub const CURVE_ORDER_ELEMENT_SIZE: usize = 32; #[cfg(feature = "ed25519")] -pub const CURVE_ORDER_ELEMENT_SIZE: usize = 28; +pub const CURVE_ORDER_ELEMENT_SIZE: usize = 32; // Byte size of element in group G1, 1 extra byte for compression flag pub const GROUP_G1_SIZE: usize = (2 * MODBYTES + 1) as usize; diff --git a/src/curve_order_elem.rs b/src/curve_order_elem.rs index 7a35781..4e32a37 100644 --- a/src/curve_order_elem.rs +++ b/src/curve_order_elem.rs @@ -609,12 +609,14 @@ impl From<&[u8; FIELD_ORDER_ELEMENT_SIZE]> for CurveOrderElement { } } +#[cfg(feature = "bls381")] impl From<[u8; CURVE_ORDER_ELEMENT_SIZE]> for CurveOrderElement { fn from(x: [u8; CURVE_ORDER_ELEMENT_SIZE]) -> Self { Self::from(&x) } } +#[cfg(feature = "bls381")] impl From<&[u8; CURVE_ORDER_ELEMENT_SIZE]> for CurveOrderElement { fn from(x: &[u8; CURVE_ORDER_ELEMENT_SIZE]) -> Self { let leading_bytes = FIELD_ORDER_ELEMENT_SIZE - CURVE_ORDER_ELEMENT_SIZE; diff --git a/src/group_elem_g1.rs b/src/group_elem_g1.rs index 758e5f0..5d8cafa 100644 --- a/src/group_elem_g1.rs +++ b/src/group_elem_g1.rs @@ -52,6 +52,7 @@ impl GroupElement for G1 { GroupG1::mapit(&hash_msg(msg)).into() } + #[cfg(feature = "bls381")] fn hash_to_curve(msg: &[u8], dst: &hash2curve::DomainSeparationTag) -> Self { let hasher = hash2curve::bls381g1::Bls12381G1Sswu::new(dst.clone()); match hasher.hash_to_curve_xmd::(msg) { @@ -62,6 +63,11 @@ impl GroupElement for G1 { } } + #[cfg(not(feature = "bls381"))] + fn hash_to_curve(msg: &[u8], dst: &hash2curve::DomainSeparationTag) -> Self { + unimplemented!(); + } + fn to_vec(&self) -> Vec { let mut bytes: [u8; GROUP_G1_SIZE] = [0; GROUP_G1_SIZE]; self.write_to_slice_unchecked(&mut bytes); From 14cd0c1e8e6843870931b2bd8e279cff96cfd362 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Tue, 21 Apr 2020 14:28:23 -0600 Subject: [PATCH 14/15] Removed comment Signed-off-by: Michael Lodder --- src/constants.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/constants.rs b/src/constants.rs index fbac943..94e18f4 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -7,7 +7,6 @@ pub const MODBYTES: usize = curve_MODBYTES; pub const NLEN: usize = curve_NLEN; pub const BIG_NUM_BITS: usize = BASEBITS; -// Byte size of element in group G1, 1 extra byte for compression flag pub const FIELD_ORDER_ELEMENT_SIZE: usize = MODBYTES; #[cfg(feature = "bls381")] pub const CURVE_ORDER_ELEMENT_SIZE: usize = 32; From 3a5607fe8d71fc57a0bac3a124e44c4f941013b9 Mon Sep 17 00:00:00 2001 From: Michael Lodder Date: Tue, 21 Apr 2020 16:11:02 -0600 Subject: [PATCH 15/15] Fixed bug in to_bytes Signed-off-by: Michael Lodder --- src/group_elem_g1.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/group_elem_g1.rs b/src/group_elem_g1.rs index 5d8cafa..dfccdda 100644 --- a/src/group_elem_g1.rs +++ b/src/group_elem_g1.rs @@ -177,7 +177,7 @@ impl G1 { } pub fn to_bytes(&self) -> [u8; 2 * FIELD_ORDER_ELEMENT_SIZE] { - let mut bytes = [0u8; FIELD_ORDER_ELEMENT_SIZE + 1]; + let mut bytes = [0u8; 2 * FIELD_ORDER_ELEMENT_SIZE + 1]; let mut temp = GroupG1::new(); temp.copy(&self.value); temp.tobytes(bytes.as_mut(), false);