diff --git a/src/ed25519.rs b/src/ed25519.rs index a4d82fc..9f000c7 100644 --- a/src/ed25519.rs +++ b/src/ed25519.rs @@ -10,7 +10,7 @@ //! A Rust implementation of ed25519 key generation, signing, and verification. use core::default::Default; -use core::fmt::{Debug}; +use core::fmt::Debug; use rand::CryptoRng; use rand::Rng; @@ -37,111 +37,8 @@ use curve25519_dalek::edwards::EdwardsPoint; use curve25519_dalek::scalar::Scalar; pub use constants::*; - -use errors::SignatureError; -use errors::InternalError; - -/// An EdDSA signature. -/// -/// # Note -/// -/// These signatures, unlike the ed25519 signature reference implementation, are -/// "detached"—that is, they do **not** include a copy of the message which has -/// been signed. -#[allow(non_snake_case)] -#[derive(Copy, Eq, PartialEq)] -pub struct Signature { - /// `R` is an `EdwardsPoint`, formed by using an hash function with - /// 512-bits output to produce the digest of: - /// - /// - the nonce half of the `ExpandedSecretKey`, and - /// - the message to be signed. - /// - /// This digest is then interpreted as a `Scalar` and reduced into an - /// element in ℤ/lℤ. The scalar is then multiplied by the distinguished - /// basepoint to produce `R`, and `EdwardsPoint`. - pub (crate) R: CompressedEdwardsY, - - /// `s` is a `Scalar`, formed by using an hash function with 512-bits output - /// to produce the digest of: - /// - /// - the `r` portion of this `Signature`, - /// - the `PublicKey` which should be used to verify this `Signature`, and - /// - the message to be signed. - /// - /// This digest is then interpreted as a `Scalar` and reduced into an - /// element in ℤ/lℤ. - pub (crate) s: Scalar, -} - -impl Clone for Signature { - fn clone(&self) -> Self { *self } -} - -impl Debug for Signature { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s) - } -} - -impl Signature { - /// Convert this `Signature` to a byte array. - #[inline] - pub fn to_bytes(&self) -> [u8; SIGNATURE_LENGTH] { - let mut signature_bytes: [u8; SIGNATURE_LENGTH] = [0u8; SIGNATURE_LENGTH]; - - signature_bytes[..32].copy_from_slice(&self.R.as_bytes()[..]); - signature_bytes[32..].copy_from_slice(&self.s.as_bytes()[..]); - signature_bytes - } - - /// Construct a `Signature` from a slice of bytes. - #[inline] - pub fn from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != SIGNATURE_LENGTH { - return Err(SignatureError(InternalError::BytesLengthError{ - name: "Signature", length: SIGNATURE_LENGTH })); - } - let mut lower: [u8; 32] = [0u8; 32]; - let mut upper: [u8; 32] = [0u8; 32]; - - lower.copy_from_slice(&bytes[..32]); - upper.copy_from_slice(&bytes[32..]); - - if upper[31] & 224 != 0 { - return Err(SignatureError(InternalError::ScalarFormatError)); - } - - Ok(Signature{ R: CompressedEdwardsY(lower), s: Scalar::from_bits(upper) }) - } -} - -#[cfg(feature = "serde")] -impl Serialize for Signature { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - serializer.serialize_bytes(&self.to_bytes()[..]) - } -} - -#[cfg(feature = "serde")] -impl<'d> Deserialize<'d> for Signature { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'d> { - struct SignatureVisitor; - - impl<'d> Visitor<'d> for SignatureVisitor { - type Value = Signature; - - fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("An ed25519 signature as 64 bytes, as specified in RFC8032.") - } - - fn visit_bytes(self, bytes: &[u8]) -> Result where E: SerdeError{ - Signature::from_bytes(bytes).or(Err(SerdeError::invalid_length(bytes.len(), &self))) - } - } - deserializer.deserialize_bytes(SignatureVisitor) - } -} +pub use errors::*; +pub use signature::*; /// An EdDSA secret key. #[derive(Default)] // we derive Default in order to use the clear() method in Drop diff --git a/src/lib.rs b/src/lib.rs index 72df455..521b34f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -263,6 +263,7 @@ extern crate bincode; mod constants; mod ed25519; +mod signature; pub mod errors; diff --git a/src/signature.rs b/src/signature.rs new file mode 100644 index 0000000..f2f2316 --- /dev/null +++ b/src/signature.rs @@ -0,0 +1,129 @@ +// -*- mode: rust; -*- +// +// This file is part of ed25519-dalek. +// Copyright (c) 2017-2018 isis lovecruft +// See LICENSE for licensing information. +// +// Authors: +// - isis agora lovecruft + +//! An ed25519 signature. + +use core::fmt::Debug; + +use curve25519_dalek::edwards::CompressedEdwardsY; +use curve25519_dalek::scalar::Scalar; + +#[cfg(feature = "serde")] +use serde::{Serialize, Deserialize}; +#[cfg(feature = "serde")] +use serde::{Serializer, Deserializer}; +#[cfg(feature = "serde")] +use serde::de::Error as SerdeError; +#[cfg(feature = "serde")] +use serde::de::Visitor; + +use constants::*; +use errors::*; + +/// An ed25519 signature. +/// +/// # Note +/// +/// These signatures, unlike the ed25519 signature reference implementation, are +/// "detached"—that is, they do **not** include a copy of the message which has +/// been signed. +#[allow(non_snake_case)] +#[derive(Copy, Eq, PartialEq)] +pub struct Signature { + /// `R` is an `EdwardsPoint`, formed by using an hash function with + /// 512-bits output to produce the digest of: + /// + /// - the nonce half of the `ExpandedSecretKey`, and + /// - the message to be signed. + /// + /// This digest is then interpreted as a `Scalar` and reduced into an + /// element in ℤ/lℤ. The scalar is then multiplied by the distinguished + /// basepoint to produce `R`, and `EdwardsPoint`. + pub (crate) R: CompressedEdwardsY, + + /// `s` is a `Scalar`, formed by using an hash function with 512-bits output + /// to produce the digest of: + /// + /// - the `r` portion of this `Signature`, + /// - the `PublicKey` which should be used to verify this `Signature`, and + /// - the message to be signed. + /// + /// This digest is then interpreted as a `Scalar` and reduced into an + /// element in ℤ/lℤ. + pub (crate) s: Scalar, +} + +impl Clone for Signature { + fn clone(&self) -> Self { *self } +} + +impl Debug for Signature { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s) + } +} + +impl Signature { + /// Convert this `Signature` to a byte array. + #[inline] + pub fn to_bytes(&self) -> [u8; SIGNATURE_LENGTH] { + let mut signature_bytes: [u8; SIGNATURE_LENGTH] = [0u8; SIGNATURE_LENGTH]; + + signature_bytes[..32].copy_from_slice(&self.R.as_bytes()[..]); + signature_bytes[32..].copy_from_slice(&self.s.as_bytes()[..]); + signature_bytes + } + + /// Construct a `Signature` from a slice of bytes. + #[inline] + pub fn from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != SIGNATURE_LENGTH { + return Err(SignatureError(InternalError::BytesLengthError{ + name: "Signature", length: SIGNATURE_LENGTH })); + } + let mut lower: [u8; 32] = [0u8; 32]; + let mut upper: [u8; 32] = [0u8; 32]; + + lower.copy_from_slice(&bytes[..32]); + upper.copy_from_slice(&bytes[32..]); + + if upper[31] & 224 != 0 { + return Err(SignatureError(InternalError::ScalarFormatError)); + } + + Ok(Signature{ R: CompressedEdwardsY(lower), s: Scalar::from_bits(upper) }) + } +} + +#[cfg(feature = "serde")] +impl Serialize for Signature { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_bytes(&self.to_bytes()[..]) + } +} + +#[cfg(feature = "serde")] +impl<'d> Deserialize<'d> for Signature { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'d> { + struct SignatureVisitor; + + impl<'d> Visitor<'d> for SignatureVisitor { + type Value = Signature; + + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + formatter.write_str("An ed25519 signature as 64 bytes, as specified in RFC8032.") + } + + fn visit_bytes(self, bytes: &[u8]) -> Result where E: SerdeError{ + Signature::from_bytes(bytes).or(Err(SerdeError::invalid_length(bytes.len(), &self))) + } + } + deserializer.deserialize_bytes(SignatureVisitor) + } +}