From 863f1dc07392ed3a9a92a2f537291c028f384f0f Mon Sep 17 00:00:00 2001 From: ryan kurte Date: Tue, 21 Mar 2023 10:36:17 +1300 Subject: [PATCH] as an alternative to #288 this updates serde `Serialize` and `Deserialize` implementations to use a custom visitor, removing the need for `alloc` or `std` for embedded use, and making this consistent with implementations in [curve25519-dalek](https://github.com/dalek-cryptography/curve25519-dalek/blob/a63e14f4ded078d6bf262ba0b3f47026bdd7f7c0/src/edwards.rs#L269). @pinkforest seems like it'd be good to have some serde tests / this should go over #289? Co-Authored-By: Vlad Semenov --- .github/workflows/rust.yml | 3 +-- Cargo.lock | 10 ---------- Cargo.toml | 3 +-- src/signing.rs | 39 +++++++++++++++++++++++++++++++------- src/verifying.rs | 39 +++++++++++++++++++++++++++++++------- 5 files changed, 66 insertions(+), 28 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 543f0ec..a70fef0 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -82,8 +82,7 @@ jobs: - uses: taiki-e/install-action@cargo-hack # No default features build - run: cargo build --target thumbv7em-none-eabi --release --no-default-features - # TODO: serde pending PR#288 - - run: cargo hack build --target thumbv7em-none-eabi --release --each-feature --exclude-features default,std,serde + - run: cargo hack build --target thumbv7em-none-eabi --release --each-feature --exclude-features default,std bench: name: Check that benchmarks compile diff --git a/Cargo.lock b/Cargo.lock index e80fe13..6c11e18 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,7 +299,6 @@ dependencies = [ "rand", "rand_core", "serde", - "serde_bytes", "serde_json", "sha2", "signature", @@ -694,15 +693,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde_bytes" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718dc5fff5b36f99093fc49b280cfc96ce6fc824317783bff5a1fed0c7a64819" -dependencies = [ - "serde", -] - [[package]] name = "serde_derive" version = "1.0.152" diff --git a/Cargo.toml b/Cargo.toml index 57bc2da..3e8a439 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,6 @@ sha2 = { version = "0.10", default-features = false } merlin = { version = "3", default-features = false, optional = true } rand_core = { version = "0.6.4", default-features = false, optional = true } serde = { version = "1.0", default-features = false, optional = true } -serde_bytes = { version = "0.11", optional = true } zeroize = { version = "1.5", default-features = false, optional = true } [dev-dependencies] @@ -68,5 +67,5 @@ legacy_compatibility = [] pkcs8 = ["ed25519/pkcs8"] pem = ["alloc", "ed25519/pem", "pkcs8"] rand_core = ["dep:rand_core"] -serde = ["dep:serde", "serde_bytes", "ed25519/serde"] +serde = ["dep:serde", "ed25519/serde"] zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"] diff --git a/src/signing.rs b/src/signing.rs index 28f7346..16f4ac6 100644 --- a/src/signing.rs +++ b/src/signing.rs @@ -15,12 +15,8 @@ use ed25519::pkcs8; #[cfg(any(test, feature = "rand_core"))] use rand_core::CryptoRngCore; -#[cfg(feature = "serde")] -use serde::de::Error as SerdeError; #[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(feature = "serde")] -use serde_bytes::{ByteBuf as SerdeByteBuf, Bytes as SerdeBytes}; use sha2::Sha512; @@ -634,7 +630,7 @@ impl Serialize for SigningKey { where S: Serializer, { - SerdeBytes::new(&self.secret_key).serialize(serializer) + serializer.serialize_bytes(&self.secret_key) } } @@ -644,8 +640,37 @@ impl<'d> Deserialize<'d> for SigningKey { where D: Deserializer<'d>, { - let bytes = ::deserialize(deserializer)?; - Self::try_from(bytes.as_ref()).map_err(SerdeError::custom) + struct SigningKeyVisitor; + + impl<'de> serde::de::Visitor<'de> for SigningKeyVisitor { + type Value = SigningKey; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(formatter, concat!("An ed25519 signing (private) key")) + } + + fn visit_borrowed_bytes( + self, + bytes: &'de [u8], + ) -> Result { + SigningKey::try_from(bytes.as_ref()).map_err(E::custom) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut bytes = [0u8; 32]; + for i in 0..32 { + bytes[i] = seq + .next_element()? + .ok_or_else(|| serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; + } + SigningKey::try_from(bytes).map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_bytes(SigningKeyVisitor) } } diff --git a/src/verifying.rs b/src/verifying.rs index 1ea9332..8816fec 100644 --- a/src/verifying.rs +++ b/src/verifying.rs @@ -27,12 +27,8 @@ use sha2::Sha512; #[cfg(feature = "pkcs8")] use ed25519::pkcs8; -#[cfg(feature = "serde")] -use serde::de::Error as SerdeError; #[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; -#[cfg(feature = "serde")] -use serde_bytes::{ByteBuf as SerdeByteBuf, Bytes as SerdeBytes}; #[cfg(feature = "digest")] use crate::context::Context; @@ -542,7 +538,7 @@ impl Serialize for VerifyingKey { where S: Serializer, { - SerdeBytes::new(self.as_bytes()).serialize(serializer) + serializer.serialize_bytes(&self.as_bytes()[..]) } } @@ -552,7 +548,36 @@ impl<'d> Deserialize<'d> for VerifyingKey { where D: Deserializer<'d>, { - let bytes = ::deserialize(deserializer)?; - VerifyingKey::try_from(bytes.as_ref()).map_err(SerdeError::custom) + struct VerifyingKeyVisitor; + + impl<'de> serde::de::Visitor<'de> for VerifyingKeyVisitor { + type Value = VerifyingKey; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(formatter, concat!("An ed25519 verifying (public) key")) + } + + fn visit_borrowed_bytes( + self, + bytes: &'de [u8], + ) -> Result { + VerifyingKey::try_from(bytes.as_ref()).map_err(E::custom) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let mut bytes = [0u8; 32]; + for i in 0..32 { + bytes[i] = seq + .next_element()? + .ok_or_else(|| serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; + } + VerifyingKey::try_from(&bytes[..]).map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_bytes(VerifyingKeyVisitor) } }