Skip to content

Commit

Permalink
Merge pull request #40 from RustCrypto/ed25519/serde
Browse files Browse the repository at this point in the history
ed25519: optional serde support
  • Loading branch information
tarcieri authored Oct 27, 2019
2 parents 6b759c3 + 26e21c8 commit 7cb1926
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 15 deletions.
11 changes: 9 additions & 2 deletions ed25519/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,12 @@ readme = "README.md"
categories = ["cryptography", "no-std"]
keywords = ["crypto", "curve25519", "ecc", "signature", "signing"]

[dependencies]
signature = { version = "1.0.0-pre.0", path = "../signature-crate", default-features = false }
[dependencies.signature]
version = "1.0.0-pre.0"
path = "../signature-crate"
default-features = false

[dependencies.serde]
version = "1"
optional = true
default-features = false
79 changes: 66 additions & 13 deletions ed25519/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
html_root_url = "https://docs.rs/ed25519/1.0.0-pre.0"
)]

#[cfg(feature = "serde")]
use serde::{de, ser, Deserialize, Serialize};

/// Re-export the `signature` crate
pub use signature::{self, Error};

Expand Down Expand Up @@ -54,10 +57,25 @@ impl signature::Signature for Signature {
}
}

impl AsRef<[u8]> for Signature {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl From<[u8; SIGNATURE_LENGTH]> for Signature {
fn from(bytes: [u8; SIGNATURE_LENGTH]) -> Signature {
Signature(bytes)
}
}

impl<'a> TryFrom<&'a [u8]> for Signature {
type Error = Error;

fn try_from(bytes: &'a [u8]) -> Result<Self, Error> {
// can't use `try_from` ourselves here because core array types only
// have TryFrom trait implementations for lengths 0..=32
// TODO(tarcieri): switch to `TryFrom` after const generics are available
if bytes.len() == SIGNATURE_LENGTH {
let mut arr = [0u8; SIGNATURE_LENGTH];
arr.copy_from_slice(bytes);
Expand All @@ -68,21 +86,12 @@ impl<'a> TryFrom<&'a [u8]> for Signature {
}
}

impl AsRef<[u8]> for Signature {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl From<[u8; SIGNATURE_LENGTH]> for Signature {
fn from(bytes: [u8; SIGNATURE_LENGTH]) -> Signature {
Signature(bytes)
}
}

// can't derive `Debug`, `PartialEq`, or `Eq` below because core array types
// only have trait implementations for lengths 0..=32
// TODO(tarcieri): derive `PartialEq` and `Eq` after const generics are available
impl Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Signature({:?})", &self.0[..])
write!(f, "ed25519::Signature({:?})", &self.0[..])
}
}

Expand All @@ -93,3 +102,47 @@ impl PartialEq for Signature {
}

impl Eq for Signature {}

#[cfg(feature = "serde")]
impl Serialize for Signature {
fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.to_bytes().serialize(serializer)
}
}

// serde lacks support for deserializing arrays larger than 32-bytes
// see: <https://github.com/serde-rs/serde/issues/631>
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Signature {
fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct ByteArrayVisitor;

impl<'de> de::Visitor<'de> for ByteArrayVisitor {
type Value = [u8; SIGNATURE_LENGTH];

fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("bytestring of length 64")
}

fn visit_seq<A>(self, mut seq: A) -> Result<[u8; SIGNATURE_LENGTH], A::Error>
where
A: de::SeqAccess<'de>,
{
use de::Error;
let mut arr = [0u8; SIGNATURE_LENGTH];

for i in 0..SIGNATURE_LENGTH {
arr[i] = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(i, &self))?;
}

Ok(arr)
}
}

deserializer
.deserialize_tuple(SIGNATURE_LENGTH, ByteArrayVisitor)
.map(|bytes| bytes.into())
}
}

0 comments on commit 7cb1926

Please sign in to comment.