diff --git a/Cargo.toml b/Cargo.toml index b50c9fb..37e5174 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ travis-ci = { repository = "dalek-cryptography/curve25519-dalek", branch = "mast [dev-dependencies] sha2 = "0.7" -serde_cbor = "0.6" +bincode = "1" criterion = "0.2" [[bench]] diff --git a/src/edwards.rs b/src/edwards.rs index 919bcb1..a09ce45 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -205,6 +205,15 @@ impl Serialize for EdwardsPoint { } } +#[cfg(feature = "serde")] +impl Serialize for CompressedEdwardsY { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.serialize_bytes(self.as_bytes()) + } +} + #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for EdwardsPoint { fn deserialize(deserializer: D) -> Result @@ -238,6 +247,37 @@ impl<'de> Deserialize<'de> for EdwardsPoint { } } +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for CompressedEdwardsY { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + struct CompressedEdwardsYVisitor; + + impl<'de> Visitor<'de> for CompressedEdwardsYVisitor { + type Value = CompressedEdwardsY; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + formatter.write_str("32 bytes of data") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where E: serde::de::Error + { + 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)) + } + } + } + + deserializer.deserialize_bytes(CompressedEdwardsYVisitor) + } +} + // ------------------------------------------------------------------------ // Internal point representations // ------------------------------------------------------------------------ @@ -1208,25 +1248,19 @@ mod test { } } - #[cfg(feature = "serde")] - use serde_cbor; - #[test] #[cfg(feature = "serde")] - fn serde_cbor_basepoint_roundtrip() { - let output = serde_cbor::to_vec(&constants::ED25519_BASEPOINT_POINT).unwrap(); - let parsed: EdwardsPoint = serde_cbor::from_slice(&output).unwrap(); - assert_eq!(parsed.compress(), constants::ED25519_BASEPOINT_COMPRESSED); - } + fn serde_bincode_basepoint_roundtrip() { + use bincode; - #[test] - #[cfg(feature = "serde")] - fn serde_cbor_decode_invalid_fails() { - let mut output = serde_cbor::to_vec(&constants::ED25519_BASEPOINT_POINT).unwrap(); - // CBOR apparently has two bytes of overhead for a 32-byte string. - // Set the low byte of the compressed point to 1 to make it invalid. - output[2] = 1; - let parsed: Result = serde_cbor::from_slice(&output); - assert!(parsed.is_err()); + let encoded = bincode::serialize(&constants::ED25519_BASEPOINT_POINT).unwrap(); + let enc_compressed = bincode::serialize(&constants::ED25519_BASEPOINT_COMPRESSED).unwrap(); + assert_eq!(encoded, enc_compressed); + + let dec_uncompressed: EdwardsPoint = bincode::deserialize(&encoded).unwrap(); + let dec_compressed: CompressedEdwardsY = bincode::deserialize(&encoded).unwrap(); + + assert_eq!(dec_uncompressed, constants::ED25519_BASEPOINT_POINT); + assert_eq!(dec_compressed, constants::ED25519_BASEPOINT_COMPRESSED); } } diff --git a/src/lib.rs b/src/lib.rs index 862c81a..267128d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,7 +57,7 @@ extern crate subtle; #[cfg(feature = "serde")] extern crate serde; #[cfg(all(test, feature = "serde"))] -extern crate serde_cbor; +extern crate bincode; // Internal macros. Must come first! #[macro_use] diff --git a/src/ristretto.rs b/src/ristretto.rs index b606c9a..8c401e3 100644 --- a/src/ristretto.rs +++ b/src/ristretto.rs @@ -323,6 +323,15 @@ impl Serialize for RistrettoPoint { } } +#[cfg(feature = "serde")] +impl Serialize for CompressedRistretto { + fn serialize(&self, serializer: S) -> Result + where S: Serializer + { + serializer.serialize_bytes(self.as_bytes()) + } +} + #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for RistrettoPoint { fn deserialize(deserializer: D) -> Result @@ -356,6 +365,37 @@ impl<'de> Deserialize<'de> for RistrettoPoint { } } +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for CompressedRistretto { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + struct CompressedRistrettoVisitor; + + impl<'de> Visitor<'de> for CompressedRistrettoVisitor { + type Value = CompressedRistretto; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + formatter.write_str("32 bytes of data") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where E: serde::de::Error + { + 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)) + } + } + } + + deserializer.deserialize_bytes(CompressedRistrettoVisitor) + } +} + // ------------------------------------------------------------------------ // Internal point representations // ------------------------------------------------------------------------ @@ -993,15 +1033,20 @@ mod test { use traits::{Identity, ValidityCheck}; use super::*; - #[cfg(feature = "serde")] - use serde_cbor; - #[test] #[cfg(feature = "serde")] - fn serde_cbor_basepoint_roundtrip() { - let output = serde_cbor::to_vec(&constants::RISTRETTO_BASEPOINT_POINT).unwrap(); - let parsed: RistrettoPoint = serde_cbor::from_slice(&output).unwrap(); - assert_eq!(parsed, constants::RISTRETTO_BASEPOINT_POINT); + fn serde_bincode_basepoint_roundtrip() { + use bincode; + + let encoded = bincode::serialize(&constants::RISTRETTO_BASEPOINT_POINT).unwrap(); + let enc_compressed = bincode::serialize(&constants::RISTRETTO_BASEPOINT_COMPRESSED).unwrap(); + assert_eq!(encoded, enc_compressed); + + let dec_uncompressed: RistrettoPoint = bincode::deserialize(&encoded).unwrap(); + let dec_compressed: CompressedRistretto = bincode::deserialize(&encoded).unwrap(); + + assert_eq!(dec_uncompressed, constants::RISTRETTO_BASEPOINT_POINT); + assert_eq!(dec_compressed, constants::RISTRETTO_BASEPOINT_COMPRESSED); } #[test] diff --git a/src/scalar.rs b/src/scalar.rs index 703369b..8c91717 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -1399,11 +1399,10 @@ mod test { #[test] #[cfg(feature = "serde")] - fn serde_cbor_scalar_roundtrip() { - // XXX remove serde_cbor - use serde_cbor; - let output = serde_cbor::to_vec(&X).unwrap(); - let parsed: Scalar = serde_cbor::from_slice(&output).unwrap(); + fn serde_bincode_scalar_roundtrip() { + use bincode; + let output = bincode::serialize(&X).unwrap(); + let parsed: Scalar = bincode::deserialize(&output).unwrap(); assert_eq!(parsed, X); }