diff --git a/Cargo.toml b/Cargo.toml index 35592f6..d154b14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ merlin = { version = "2", default-features = false, optional = true } rand = { version = "0.7", default-features = false, optional = true } rand_core = { version = "0.5", default-features = false, optional = true } serde_crate = { package = "serde", version = "1.0", default-features = false, optional = true } +serde_bytes = { version = "0.11", optional = true } sha2 = { version = "0.9", default-features = false } zeroize = { version = "1", default-features = false, features = ["zeroize_derive"] } @@ -52,7 +53,7 @@ default = ["std", "rand", "u64_backend"] std = ["curve25519-dalek/std", "ed25519/std", "serde_crate/std", "sha2/std", "rand/std"] alloc = ["curve25519-dalek/alloc", "rand/alloc", "zeroize/alloc"] nightly = ["curve25519-dalek/nightly"] -serde = ["serde_crate", "ed25519/serde"] +serde = ["serde_crate", "serde_bytes", "ed25519/serde"] batch = ["merlin", "rand"] # This feature enables deterministic batch verification. batch_deterministic = ["merlin", "rand", "rand_core"] diff --git a/src/keypair.rs b/src/keypair.rs index c12f751..55af2df 100644 --- a/src/keypair.rs +++ b/src/keypair.rs @@ -15,11 +15,9 @@ use rand::{CryptoRng, RngCore}; #[cfg(feature = "serde")] use serde::de::Error as SerdeError; #[cfg(feature = "serde")] -use serde::de::Visitor; -#[cfg(feature = "serde")] -use serde::de::SeqAccess; -#[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "serde")] +use serde_bytes::{Bytes as SerdeBytes, ByteBuf as SerdeByteBuf}; pub use sha2::Sha512; @@ -428,7 +426,8 @@ impl Serialize for Keypair { where S: Serializer, { - serializer.serialize_bytes(&self.to_bytes()[..]) + let bytes = &self.to_bytes()[..]; + SerdeBytes::new(bytes).serialize(serializer) } } @@ -438,63 +437,7 @@ impl<'d> Deserialize<'d> for Keypair { where D: Deserializer<'d>, { - struct KeypairVisitor; - - impl<'d> Visitor<'d> for KeypairVisitor { - type Value = Keypair; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - formatter.write_str("An ed25519 keypair, 64 bytes in total where the secret key is \ - the first 32 bytes and is in unexpanded form, and the second \ - 32 bytes is a compressed point for a public key.") - } - - fn visit_bytes(self, bytes: &[u8]) -> Result - where - E: SerdeError, - { - if bytes.len() != KEYPAIR_LENGTH { - return Err(SerdeError::invalid_length(bytes.len(), &self)); - } - - let secret_key = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH]); - let public_key = PublicKey::from_bytes(&bytes[SECRET_KEY_LENGTH..]); - - if let (Ok(secret), Ok(public)) = (secret_key, public_key) { - Ok(Keypair{ secret, public }) - } else { - Err(SerdeError::invalid_length(bytes.len(), &self)) - } - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'d> - { - if let Some(len) = seq.size_hint() { - if len != KEYPAIR_LENGTH { - return Err(SerdeError::invalid_length(len, &self)); - } - } - - // TODO: We could do this with `MaybeUninit` to avoid unnecessary initialization costs - let mut bytes: [u8; KEYPAIR_LENGTH] = [0u8; KEYPAIR_LENGTH]; - - for i in 0..KEYPAIR_LENGTH { - bytes[i] = seq.next_element()?.ok_or_else(|| SerdeError::invalid_length(i, &self))?; - } - - let secret_key = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH]); - let public_key = PublicKey::from_bytes(&bytes[SECRET_KEY_LENGTH..]); - - if let (Ok(secret), Ok(public)) = (secret_key, public_key) { - Ok(Keypair{ secret, public }) - } else { - Err(SerdeError::invalid_length(bytes.len(), &self)) - } - } - - } - deserializer.deserialize_bytes(KeypairVisitor) + let bytes = ::deserialize(deserializer)?; + Keypair::from_bytes(bytes.as_ref()).map_err(SerdeError::custom) } } diff --git a/src/public.rs b/src/public.rs index 170390d..342adf6 100644 --- a/src/public.rs +++ b/src/public.rs @@ -26,11 +26,9 @@ pub use sha2::Sha512; #[cfg(feature = "serde")] use serde::de::Error as SerdeError; #[cfg(feature = "serde")] -use serde::de::Visitor; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; -#[cfg(feature = "serde")] -use serde::{Deserializer, Serializer}; +use serde_bytes::{Bytes as SerdeBytes, ByteBuf as SerdeByteBuf}; use crate::constants::*; use crate::errors::*; @@ -362,7 +360,7 @@ impl Serialize for PublicKey { where S: Serializer, { - serializer.serialize_bytes(self.as_bytes()) + SerdeBytes::new(self.as_bytes()).serialize(serializer) } } @@ -372,24 +370,7 @@ impl<'d> Deserialize<'d> for PublicKey { where D: Deserializer<'d>, { - struct PublicKeyVisitor; - - impl<'d> Visitor<'d> for PublicKeyVisitor { - type Value = PublicKey; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - formatter.write_str( - "An ed25519 public key as a 32-byte compressed point, as specified in RFC8032", - ) - } - - fn visit_bytes(self, bytes: &[u8]) -> Result - where - E: SerdeError, - { - PublicKey::from_bytes(bytes).or(Err(SerdeError::invalid_length(bytes.len(), &self))) - } - } - deserializer.deserialize_bytes(PublicKeyVisitor) + let bytes = ::deserialize(deserializer)?; + PublicKey::from_bytes(bytes.as_ref()).map_err(SerdeError::custom) } } diff --git a/src/secret.rs b/src/secret.rs index 64c9d1f..2ca3a12 100644 --- a/src/secret.rs +++ b/src/secret.rs @@ -25,11 +25,9 @@ use sha2::Sha512; #[cfg(feature = "serde")] use serde::de::Error as SerdeError; #[cfg(feature = "serde")] -use serde::de::Visitor; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; -#[cfg(feature = "serde")] -use serde::{Deserializer, Serializer}; +use serde_bytes::{Bytes as SerdeBytes, ByteBuf as SerdeByteBuf}; use zeroize::Zeroize; @@ -184,7 +182,7 @@ impl Serialize for SecretKey { where S: Serializer, { - serializer.serialize_bytes(self.as_bytes()) + SerdeBytes::new(self.as_bytes()).serialize(serializer) } } @@ -194,23 +192,8 @@ impl<'d> Deserialize<'d> for SecretKey { where D: Deserializer<'d>, { - struct SecretKeyVisitor; - - impl<'d> Visitor<'d> for SecretKeyVisitor { - type Value = SecretKey; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - formatter.write_str("An ed25519 secret key as 32 bytes, as specified in RFC8032.") - } - - fn visit_bytes(self, bytes: &[u8]) -> Result - where - E: SerdeError, - { - SecretKey::from_bytes(bytes).or(Err(SerdeError::invalid_length(bytes.len(), &self))) - } - } - deserializer.deserialize_bytes(SecretKeyVisitor) + let bytes = ::deserialize(deserializer)?; + SecretKey::from_bytes(bytes.as_ref()).map_err(SerdeError::custom) } } @@ -521,7 +504,8 @@ impl Serialize for ExpandedSecretKey { where S: Serializer, { - serializer.serialize_bytes(&self.to_bytes()[..]) + let bytes = &self.to_bytes()[..]; + SerdeBytes::new(bytes).serialize(serializer) } } @@ -531,26 +515,8 @@ impl<'d> Deserialize<'d> for ExpandedSecretKey { where D: Deserializer<'d>, { - struct ExpandedSecretKeyVisitor; - - impl<'d> Visitor<'d> for ExpandedSecretKeyVisitor { - type Value = ExpandedSecretKey; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - formatter.write_str( - "An ed25519 expanded secret key as 64 bytes, as specified in RFC8032.", - ) - } - - fn visit_bytes(self, bytes: &[u8]) -> Result - where - E: SerdeError, - { - ExpandedSecretKey::from_bytes(bytes) - .or(Err(SerdeError::invalid_length(bytes.len(), &self))) - } - } - deserializer.deserialize_bytes(ExpandedSecretKeyVisitor) + let bytes = ::deserialize(deserializer)?; + ExpandedSecretKey::from_bytes(bytes.as_ref()).map_err(SerdeError::custom) } }