diff --git a/src/bls12_381/ec.rs b/src/bls12_381/ec.rs index fe12374..2f39940 100644 --- a/src/bls12_381/ec.rs +++ b/src/bls12_381/ec.rs @@ -617,8 +617,6 @@ pub mod g1 { } } fn into_affine_unchecked(&self) -> Result { - use byteorder::{ReadBytesExt, BigEndian}; - // Create a copy of this representation. let mut copy = self.0; @@ -654,13 +652,8 @@ pub mod g1 { { let mut reader = ©[..]; - for b in x.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } - - for b in y.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } + x.read_be(&mut reader).unwrap(); + y.read_be(&mut reader).unwrap(); } Ok(G1Affine { @@ -671,8 +664,6 @@ pub mod g1 { } } fn from_affine(affine: G1Affine) -> Self { - use byteorder::{WriteBytesExt, BigEndian}; - let mut res = Self::empty(); if affine.is_zero() { @@ -682,13 +673,8 @@ pub mod g1 { } else { let mut writer = &mut res.0[..]; - for digit in affine.x.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } - - for digit in affine.y.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } + affine.x.into_repr().write_be(&mut writer).unwrap(); + affine.y.into_repr().write_be(&mut writer).unwrap(); } res @@ -733,8 +719,6 @@ pub mod g1 { } } fn into_affine_unchecked(&self) -> Result { - use byteorder::{ReadBytesExt, BigEndian}; - // Create a copy of this representation. let mut copy = self.0; @@ -767,9 +751,7 @@ pub mod g1 { { let mut reader = ©[..]; - for b in x.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } + x.read_be(&mut reader).unwrap(); } // Interpret as Fq element. @@ -804,8 +786,6 @@ pub mod g1 { } } fn from_affine(affine: G1Affine) -> Self { - use byteorder::{WriteBytesExt, BigEndian}; - let mut res = Self::empty(); if affine.is_zero() { @@ -816,9 +796,7 @@ pub mod g1 { { let mut writer = &mut res.0[..]; - for digit in affine.x.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } + affine.x.into_repr().write_be(&mut writer).unwrap(); } let mut negy = affine.y; @@ -1187,8 +1165,6 @@ pub mod g2 { } } fn into_affine_unchecked(&self) -> Result { - use byteorder::{ReadBytesExt, BigEndian}; - // Create a copy of this representation. let mut copy = self.0; @@ -1226,21 +1202,10 @@ pub mod g2 { { let mut reader = ©[..]; - for b in x_c1.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } - - for b in x_c0.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } - - for b in y_c1.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } - - for b in y_c0.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } + x_c1.read_be(&mut reader).unwrap(); + x_c0.read_be(&mut reader).unwrap(); + y_c1.read_be(&mut reader).unwrap(); + y_c0.read_be(&mut reader).unwrap(); } Ok(G2Affine { @@ -1257,8 +1222,6 @@ pub mod g2 { } } fn from_affine(affine: G2Affine) -> Self { - use byteorder::{WriteBytesExt, BigEndian}; - let mut res = Self::empty(); if affine.is_zero() { @@ -1268,21 +1231,10 @@ pub mod g2 { } else { let mut writer = &mut res.0[..]; - for digit in affine.x.c1.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } - - for digit in affine.x.c0.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } - - for digit in affine.y.c1.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } - - for digit in affine.y.c0.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } + affine.x.c1.into_repr().write_be(&mut writer).unwrap(); + affine.x.c0.into_repr().write_be(&mut writer).unwrap(); + affine.y.c1.into_repr().write_be(&mut writer).unwrap(); + affine.y.c0.into_repr().write_be(&mut writer).unwrap(); } res @@ -1327,8 +1279,6 @@ pub mod g2 { } } fn into_affine_unchecked(&self) -> Result { - use byteorder::{ReadBytesExt, BigEndian}; - // Create a copy of this representation. let mut copy = self.0; @@ -1362,13 +1312,8 @@ pub mod g2 { { let mut reader = ©[..]; - for b in x_c1.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } - - for b in x_c0.0.iter_mut().rev() { - *b = reader.read_u64::().unwrap(); - } + x_c1.read_be(&mut reader).unwrap(); + x_c0.read_be(&mut reader).unwrap(); } // Interpret as Fq element. @@ -1406,8 +1351,6 @@ pub mod g2 { } } fn from_affine(affine: G2Affine) -> Self { - use byteorder::{WriteBytesExt, BigEndian}; - let mut res = Self::empty(); if affine.is_zero() { @@ -1418,13 +1361,8 @@ pub mod g2 { { let mut writer = &mut res.0[..]; - for digit in affine.x.c1.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } - - for digit in affine.x.c0.into_repr().as_ref().iter().rev() { - writer.write_u64::(*digit).unwrap(); - } + affine.x.c1.into_repr().write_be(&mut writer).unwrap(); + affine.x.c0.into_repr().write_be(&mut writer).unwrap(); } let mut negy = affine.y; diff --git a/src/bls12_381/fq.rs b/src/bls12_381/fq.rs index 2c512c8..00b0405 100644 --- a/src/bls12_381/fq.rs +++ b/src/bls12_381/fq.rs @@ -221,6 +221,13 @@ impl AsRef<[u64]> for FqRepr { } } +impl AsMut<[u64]> for FqRepr { + #[inline(always)] + fn as_mut(&mut self) -> &mut [u64] { + &mut self.0 + } +} + impl From for FqRepr { #[inline(always)] fn from(val: u64) -> FqRepr { diff --git a/src/bls12_381/fr.rs b/src/bls12_381/fr.rs index b1927bf..c321b76 100644 --- a/src/bls12_381/fr.rs +++ b/src/bls12_381/fr.rs @@ -57,6 +57,13 @@ impl AsRef<[u64]> for FrRepr { } } +impl AsMut<[u64]> for FrRepr { + #[inline(always)] + fn as_mut(&mut self) -> &mut [u64] { + &mut self.0 + } +} + impl From for FrRepr { #[inline(always)] fn from(val: u64) -> FrRepr { diff --git a/src/lib.rs b/src/lib.rs index 54f61b1..326e436 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ pub mod wnaf; use std::fmt; use std::error::Error; +use std::io::{self, Read, Write}; /// An "engine" is a collection of types (fields, elliptic curve groups, etc.) /// with well-defined relationships. In particular, the G1/G2 curve groups are @@ -336,6 +337,7 @@ pub trait PrimeFieldRepr: Sized + 'static + rand::Rand + AsRef<[u64]> + + AsMut<[u64]> + From { /// Subtract another reprensetation from this one, returning the borrow bit. @@ -366,6 +368,30 @@ pub trait PrimeFieldRepr: Sized + /// Performs a leftwise bitshift of this number, effectively multiplying /// it by 2. Overflow is ignored. fn mul2(&mut self); + + /// Writes this `PrimeFieldRepr` as a big endian integer. Always writes + /// `(num_bits` / 8) bytes. + fn write_be(&self, mut writer: W) -> io::Result<()> { + use byteorder::{WriteBytesExt, BigEndian}; + + for digit in self.as_ref().iter().rev() { + writer.write_u64::(*digit)?; + } + + Ok(()) + } + + /// Reads a big endian integer occupying (`num_bits` / 8) bytes into this + /// representation. + fn read_be(&mut self, mut reader: R) -> io::Result<()> { + use byteorder::{ReadBytesExt, BigEndian}; + + for digit in self.as_mut().iter_mut().rev() { + *digit = reader.read_u64::()?; + } + + Ok(()) + } } /// An error that may occur when trying to interpret a `PrimeFieldRepr` as a