#![no_std]
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms, unused_qualifications)]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png",
html_root_url = "https://docs.rs/ed25519/1.0.0"
)]
#[cfg(feature = "serde")]
use serde::{de, ser, Deserialize, Serialize};
#[cfg(all(test, feature = "std"))]
extern crate std;
pub use signature::{self, Error};
use core::{
convert::{TryFrom, TryInto},
fmt::{self, Debug},
};
pub const SIGNATURE_LENGTH: usize = 64;
#[derive(Copy, Clone)]
pub struct Signature([u8; SIGNATURE_LENGTH]);
impl Signature {
pub fn new(bytes: [u8; SIGNATURE_LENGTH]) -> Self {
Self::from(bytes)
}
pub fn to_bytes(&self) -> [u8; SIGNATURE_LENGTH] {
self.0
}
}
impl signature::Signature for Signature {
fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
bytes.try_into()
}
}
impl AsRef<[u8]> for Signature {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ed25519::Signature({:?})", &self.0[..])
}
}
impl Eq for Signature {}
impl PartialEq for Signature {
fn eq(&self, other: &Self) -> bool {
self.as_ref().eq(other.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> {
if bytes.len() != SIGNATURE_LENGTH {
return Err(Error::new());
}
if bytes[SIGNATURE_LENGTH - 1] & 0b1110_0000 != 0 {
return Err(Error::new());
}
let mut arr = [0u8; SIGNATURE_LENGTH];
arr.copy_from_slice(bytes);
Ok(Signature(arr))
}
}
#[cfg(feature = "serde")]
impl Serialize for Signature {
fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use ser::SerializeTuple;
let mut seq = serializer.serialize_tuple(SIGNATURE_LENGTH)?;
for byte in &self.0[..] {
seq.serialize_element(byte)?;
}
seq.end()
}
}
#[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, byte) in arr.iter_mut().enumerate() {
*byte = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(i, &self))?;
}
Ok(arr)
}
}
deserializer
.deserialize_tuple(SIGNATURE_LENGTH, ByteArrayVisitor)
.map(|bytes| bytes.into())
}
}
#[cfg(all(test, feature = "serde", feature = "std"))]
mod tests {
use super::*;
use signature::Signature as _;
use std::{convert::TryFrom, vec::Vec};
const EXAMPLE_SIGNATURE: [u8; SIGNATURE_LENGTH] = [
63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41,
40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18,
17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
];
#[test]
fn test_serialize() {
let signature = Signature::try_from(&EXAMPLE_SIGNATURE[..]).unwrap();
let encoded_signature: Vec<u8> = bincode::serialize(&signature).unwrap();
assert_eq!(&EXAMPLE_SIGNATURE[..], &encoded_signature[..]);
}
#[test]
fn test_deserialize() {
let signature = bincode::deserialize::<Signature>(&EXAMPLE_SIGNATURE).unwrap();
assert_eq!(&EXAMPLE_SIGNATURE[..], signature.as_bytes());
}
}