Use "tuples" instead of "bytes" in the Serde datamodel.

This is a breaking change to the serialization format.  It fixes it so that the
Serde encoding can match the conventional encoding of each type of object, and
so that Serde can be used with no overhead -- when using serde-bincode, the
Serde encoding now matches the manual encoding.
This commit is contained in:
Henry de Valence 2019-10-23 14:49:55 -07:00
parent 29ce0d4fe9
commit 0fc534d989
4 changed files with 79 additions and 65 deletions

View file

@ -1,6 +1,6 @@
[package]
name = "curve25519-dalek"
version = "1.2.3"
version = "2.0.0-alpha.0"
authors = ["Isis Lovecruft <isis@patternsinthevoid.net>",
"Henry de Valence <hdevalence@hdevalence.ca>"]
readme = "README.md"

View file

@ -217,7 +217,12 @@ impl Serialize for EdwardsPoint {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_bytes(self.compress().as_bytes())
use serde::ser::SerializeTuple;
let mut tup = serializer.serialize_tuple(32)?;
for byte in self.compress().as_bytes().iter() {
tup.serialize_element(byte)?;
}
tup.end()
}
}
@ -226,7 +231,12 @@ impl Serialize for CompressedEdwardsY {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_bytes(self.as_bytes())
use serde::ser::SerializeTuple;
let mut tup = serializer.serialize_tuple(32)?;
for byte in self.as_bytes().iter() {
tup.serialize_element(byte)?;
}
tup.end()
}
}
@ -244,22 +254,21 @@ impl<'de> Deserialize<'de> for EdwardsPoint {
formatter.write_str("a valid point in Edwards y + sign format")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<EdwardsPoint, E>
where E: serde::de::Error
fn visit_seq<A>(self, mut seq: A) -> Result<EdwardsPoint, A::Error>
where A: serde::de::SeqAccess<'de>
{
if v.len() == 32 {
let mut arr32 = [0u8; 32];
arr32[0..32].copy_from_slice(v);
CompressedEdwardsY(arr32)
.decompress()
.ok_or(serde::de::Error::custom("decompression failed"))
} else {
Err(serde::de::Error::invalid_length(v.len(), &self))
let mut bytes = [0u8; 32];
for i in 0..32 {
bytes[i] = seq.next_element()?
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
}
CompressedEdwardsY(bytes)
.decompress()
.ok_or(serde::de::Error::custom("decompression failed"))
}
}
deserializer.deserialize_bytes(EdwardsPointVisitor)
deserializer.deserialize_tuple(32, EdwardsPointVisitor)
}
}
@ -277,20 +286,19 @@ impl<'de> Deserialize<'de> for CompressedEdwardsY {
formatter.write_str("32 bytes of data")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<CompressedEdwardsY, E>
where E: serde::de::Error
fn visit_seq<A>(self, mut seq: A) -> Result<CompressedEdwardsY, A::Error>
where A: serde::de::SeqAccess<'de>
{
if v.len() == 32 {
let mut arr32 = [0u8; 32];
arr32[0..32].copy_from_slice(v);
Ok(CompressedEdwardsY(arr32))
} else {
Err(serde::de::Error::invalid_length(v.len(), &self))
let mut bytes = [0u8; 32];
for i in 0..32 {
bytes[i] = seq.next_element()?
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
}
Ok(CompressedEdwardsY(bytes))
}
}
deserializer.deserialize_bytes(CompressedEdwardsYVisitor)
deserializer.deserialize_tuple(32, CompressedEdwardsYVisitor)
}
}

View file

@ -334,7 +334,12 @@ impl Serialize for RistrettoPoint {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_bytes(self.compress().as_bytes())
use serde::ser::SerializeTuple;
let mut tup = serializer.serialize_tuple(32)?;
for byte in self.compress().as_bytes().iter() {
tup.serialize_element(byte)?;
}
tup.end()
}
}
@ -343,7 +348,12 @@ impl Serialize for CompressedRistretto {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_bytes(self.as_bytes())
use serde::ser::SerializeTuple;
let mut tup = serializer.serialize_tuple(32)?;
for byte in self.as_bytes().iter() {
tup.serialize_element(byte)?;
}
tup.end()
}
}
@ -361,22 +371,21 @@ impl<'de> Deserialize<'de> for RistrettoPoint {
formatter.write_str("a valid point in Ristretto format")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<RistrettoPoint, E>
where E: serde::de::Error
fn visit_seq<A>(self, mut seq: A) -> Result<RistrettoPoint, A::Error>
where A: serde::de::SeqAccess<'de>
{
if v.len() == 32 {
let mut arr32 = [0u8; 32];
arr32[0..32].copy_from_slice(v);
CompressedRistretto(arr32)
.decompress()
.ok_or(serde::de::Error::custom("decompression failed"))
} else {
Err(serde::de::Error::invalid_length(v.len(), &self))
let mut bytes = [0u8; 32];
for i in 0..32 {
bytes[i] = seq.next_element()?
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
}
CompressedRistretto(bytes)
.decompress()
.ok_or(serde::de::Error::custom("decompression failed"))
}
}
deserializer.deserialize_bytes(RistrettoPointVisitor)
deserializer.deserialize_tuple(32, RistrettoPointVisitor)
}
}
@ -394,20 +403,19 @@ impl<'de> Deserialize<'de> for CompressedRistretto {
formatter.write_str("32 bytes of data")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<CompressedRistretto, E>
where E: serde::de::Error
fn visit_seq<A>(self, mut seq: A) -> Result<CompressedRistretto, A::Error>
where A: serde::de::SeqAccess<'de>
{
if v.len() == 32 {
let mut arr32 = [0u8; 32];
arr32[0..32].copy_from_slice(v);
Ok(CompressedRistretto(arr32))
} else {
Err(serde::de::Error::invalid_length(v.len(), &self))
let mut bytes = [0u8; 32];
for i in 0..32 {
bytes[i] = seq.next_element()?
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
}
Ok(CompressedRistretto(bytes))
}
}
deserializer.deserialize_bytes(CompressedRistrettoVisitor)
deserializer.deserialize_tuple(32, CompressedRistrettoVisitor)
}
}

View file

@ -385,7 +385,12 @@ impl Serialize for Scalar {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
serializer.serialize_bytes(self.reduce().as_bytes())
use serde::ser::SerializeTuple;
let mut tup = serializer.serialize_tuple(32)?;
for byte in self.as_bytes().iter() {
tup.serialize_element(byte)?;
}
tup.end()
}
}
@ -400,32 +405,25 @@ impl<'de> Deserialize<'de> for Scalar {
type Value = Scalar;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
formatter.write_str("a canonically-encoded 32-byte scalar value")
formatter.write_str("a valid point in Edwards y + sign format")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Scalar, E>
where E: serde::de::Error
fn visit_seq<A>(self, mut seq: A) -> Result<Scalar, A::Error>
where A: serde::de::SeqAccess<'de>
{
if v.len() == 32 {
let mut bytes = [0u8;32];
bytes.copy_from_slice(v);
static ERRMSG: &'static str = "encoding was not canonical";
Scalar::from_canonical_bytes(bytes)
.ok_or(
serde::de::Error::invalid_value(
serde::de::Unexpected::Bytes(v),
&ERRMSG,
)
)
} else {
Err(serde::de::Error::invalid_length(v.len(), &self))
let mut bytes = [0u8; 32];
for i in 0..32 {
bytes[i] = seq.next_element()?
.ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?;
}
Scalar::from_canonical_bytes(bytes)
.ok_or(serde::de::Error::custom(
&"scalar was not canonically encoded"
))
}
}
deserializer.deserialize_bytes(ScalarVisitor)
deserializer.deserialize_tuple(32, ScalarVisitor)
}
}