diff --git a/src/arithmetic/curves.rs b/src/arithmetic/curves.rs index 6210031e..fa6512c3 100644 --- a/src/arithmetic/curves.rs +++ b/src/arithmetic/curves.rs @@ -8,6 +8,8 @@ use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use super::{FieldExt, Group}; +use std::io::{self, Read, Write}; + /// This trait is a common interface for dealing with elements of an elliptic /// curve group in the "projective" form, where that arithmetic is usually more /// efficient. @@ -153,10 +155,27 @@ pub trait CurveAffine: /// endian representation. fn from_bytes(bytes: &[u8; 32]) -> CtOption; + /// Reads a compressed element from the buffer and attempts to parse it + /// using `from_bytes`. + fn read(reader: &mut R) -> io::Result { + let mut compressed = [0u8; 32]; + reader.read_exact(&mut compressed[..])?; + Option::from(Self::from_bytes(&compressed)).ok_or(io::Error::new( + io::ErrorKind::Other, + "invalid point encoding in proof", + )) + } + /// Obtains the compressed, 32-byte little endian representation of this /// element. fn to_bytes(&self) -> [u8; 32]; + /// Writes an element in compressed form to the buffer. + fn write(&self, writer: &mut W) -> io::Result<()> { + let compressed = self.to_bytes(); + writer.write_all(&compressed[..]) + } + /// Attempts to obtain a group element from its uncompressed 64-byte little /// endian representation. fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption; diff --git a/src/arithmetic/fields.rs b/src/arithmetic/fields.rs index 6a35cc00..3d0dfcb2 100644 --- a/src/arithmetic/fields.rs +++ b/src/arithmetic/fields.rs @@ -10,6 +10,8 @@ use subtle::{Choice, ConstantTimeEq, CtOption}; use super::Group; +use std::io::{self, Read, Write}; + const_assert!(size_of::() >= 4); /// This trait is a common interface for dealing with elements of a finite @@ -77,10 +79,27 @@ pub trait FieldExt: /// representation. fn to_bytes(&self) -> [u8; 32]; + /// Writes this element in its normalized, little endian form into a buffer. + fn write(&self, writer: &mut W) -> io::Result<()> { + let compressed = self.to_bytes(); + writer.write_all(&compressed[..]) + } + /// Attempts to obtain a field element from its normalized, little endian /// byte representation. fn from_bytes(bytes: &[u8; 32]) -> CtOption; + /// Reads a normalized, little endian represented field element from a + /// buffer. + fn read(reader: &mut R) -> io::Result { + let mut compressed = [0u8; 32]; + reader.read_exact(&mut compressed[..])?; + Option::from(Self::from_bytes(&compressed)).ok_or(io::Error::new( + io::ErrorKind::Other, + "invalid point encoding in proof", + )) + } + /// Obtains a field element that is congruent to the provided little endian /// byte representation of an integer. fn from_bytes_wide(bytes: &[u8; 64]) -> Self;