Merge branch 'release/0.6.0'

This commit is contained in:
Isis Lovecruft 2018-01-20 03:07:16 +00:00
commit a40bc4c6fd
Failed to extract signature
6 changed files with 220 additions and 97 deletions

View file

@ -27,3 +27,8 @@ matrix:
script: script:
- cargo $TEST_COMMAND $FEATURES - cargo $TEST_COMMAND $FEATURES
notifications:
slack:
rooms:
- dalek-cryptography:Xxv9WotKYWdSoKlgKNqXiHoD#dalek-bots

View file

@ -1,11 +1,11 @@
[package] [package]
name = "ed25519-dalek" name = "ed25519-dalek"
version = "0.5.0" version = "0.6.0"
authors = ["Isis Lovecruft <isis@torproject.org>"] authors = ["Isis Lovecruft <isis@patternsinthevoid.net>"]
readme = "README.md" readme = "README.md"
license = "BSD-3-Clause" license = "BSD-3-Clause"
repository = "https://github.com/isislovecruft/ed25519-dalek" repository = "https://github.com/dalek-cryptography/ed25519-dalek"
homepage = "https://code.ciph.re/isis/ed25519-dalek" homepage = "https://dalek.rs"
documentation = "https://docs.rs/ed25519-dalek" documentation = "https://docs.rs/ed25519-dalek"
keywords = ["cryptography", "ed25519", "curve25519", "signature", "ECC"] keywords = ["cryptography", "ed25519", "curve25519", "signature", "ECC"]
categories = ["cryptography", "no-std"] categories = ["cryptography", "no-std"]
@ -15,44 +15,45 @@ exclude = [ ".gitignore", "TESTVECTORS", "res/*" ]
[badges] [badges]
travis-ci = { repository = "isislovecruft/ed25519-dalek", branch = "master"} travis-ci = { repository = "isislovecruft/ed25519-dalek", branch = "master"}
[dependencies]
arrayref = "0.3.4"
[dependencies.curve25519-dalek] [dependencies.curve25519-dalek]
version = "^0.12" version = "0.14"
default-features = false default-features = false
[dependencies.subtle] [dependencies.subtle]
version = "^0.3" version = "0.5"
default-features = false default-features = false
[dependencies.rand] [dependencies.rand]
optional = true optional = true
version = "^0.3" version = "0.4"
[dependencies.digest] [dependencies.digest]
version = "^0.6" version = "0.6"
[dependencies.generic-array] [dependencies.generic-array]
# same version that digest depends on # same version that digest depends on
version = "^0.8" version = "0.9"
[dependencies.serde] [dependencies.serde]
version = "^1.0" version = "^1.0"
optional = true optional = true
[dependencies.sha2] [dependencies.sha2]
version = "^0.6" version = "0.6"
optional = true optional = true
[dependencies.failure]
version = "^0.1.1"
default-features = false
[dev-dependencies] [dev-dependencies]
hex = "0.2" hex = "0.3"
sha2 = "^0.6" sha2 = "0.6"
bincode = "^0.9" bincode = "^0.9"
[features] [features]
default = ["std"] default = ["std"]
std = ["rand", "curve25519-dalek/std"] std = ["rand", "curve25519-dalek/std", "failure/std"]
bench = [] bench = []
nightly = ["curve25519-dalek/nightly"] nightly = ["curve25519-dalek/nightly"]
asm = ["sha2/asm"] asm = ["sha2/asm"]

View file

@ -119,7 +119,7 @@ eventually support VXEdDSA in curve25519-dalek.
To install, add the following to your project's `Cargo.toml`: To install, add the following to your project's `Cargo.toml`:
[dependencies.ed25519-dalek] [dependencies.ed25519-dalek]
version = "^0.5" version = "^0.6"
Then, in your library or executable source, add: Then, in your library or executable source, add:
@ -129,7 +129,7 @@ To cause your application to build `ed25519-dalek` with the nightly feature
enabled by default, instead do: enabled by default, instead do:
[dependencies.ed25519-dalek] [dependencies.ed25519-dalek]
version = "^0.5" version = "^0.6"
features = ["nightly"] features = ["nightly"]
To cause your application to instead build with the nightly feature enabled To cause your application to instead build with the nightly feature enabled
@ -145,7 +145,7 @@ verification.
To enable [serde](https://serde.rs) support, build `ed25519-dalek` with: To enable [serde](https://serde.rs) support, build `ed25519-dalek` with:
[dependencies.ed25519-dalek] [dependencies.ed25519-dalek]
version = "^0.5" version = "^0.6"
features = ["serde"] features = ["serde"]

View file

@ -10,7 +10,7 @@
//! A Rust implementation of ed25519 EdDSA key generation, signing, and //! A Rust implementation of ed25519 EdDSA key generation, signing, and
//! verification. //! verification.
use core::fmt::Debug; use core::fmt::{Debug};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use rand::Rng; use rand::Rng;
@ -27,10 +27,7 @@ use serde::de::Visitor;
#[cfg(feature = "sha2")] #[cfg(feature = "sha2")]
use sha2::Sha512; use sha2::Sha512;
use digest::BlockInput;
use digest::Digest; use digest::Digest;
use digest::Input;
use digest::FixedOutput;
use generic_array::typenum::U64; use generic_array::typenum::U64;
@ -41,10 +38,13 @@ use curve25519_dalek::scalar::Scalar;
use subtle::slices_equal; use subtle::slices_equal;
/// The length of an ed25519 EdDSA `Signature`, in bytes. use errors::DecodingError;
use errors::InternalError;
/// The length of a curve25519 EdDSA `Signature`, in bytes.
pub const SIGNATURE_LENGTH: usize = 64; pub const SIGNATURE_LENGTH: usize = 64;
/// The length of an ed25519 EdDSA `SecretKey`, in bytes. /// The length of a curve25519 EdDSA `SecretKey`, in bytes.
pub const SECRET_KEY_LENGTH: usize = 32; pub const SECRET_KEY_LENGTH: usize = 32;
/// The length of an ed25519 EdDSA `PublicKey`, in bytes. /// The length of an ed25519 EdDSA `PublicKey`, in bytes.
@ -53,6 +53,15 @@ pub const PUBLIC_KEY_LENGTH: usize = 32;
/// The length of an ed25519 EdDSA `Keypair`, in bytes. /// The length of an ed25519 EdDSA `Keypair`, in bytes.
pub const KEYPAIR_LENGTH: usize = SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH; pub const KEYPAIR_LENGTH: usize = SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH;
/// The length of the "key" portion of an "expanded" curve25519 EdDSA secret key, in bytes.
const EXPANDED_SECRET_KEY_KEY_LENGTH: usize = 32;
/// The length of the "nonce" portion of an "expanded" curve25519 EdDSA secret key, in bytes.
const EXPANDED_SECRET_KEY_NONCE_LENGTH: usize = 32;
/// The length of an "expanded" curve25519 EdDSA key, `ExpandedSecretKey`, in bytes.
pub const EXPANDED_SECRET_KEY_LENGTH: usize = EXPANDED_SECRET_KEY_KEY_LENGTH + EXPANDED_SECRET_KEY_NONCE_LENGTH;
/// An EdDSA signature. /// An EdDSA signature.
/// ///
/// # Note /// # Note
@ -123,15 +132,22 @@ impl Signature {
/// Construct a `Signature` from a slice of bytes. /// Construct a `Signature` from a slice of bytes.
#[inline] #[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<Signature, &'static str> { pub fn from_bytes(bytes: &[u8]) -> Result<Signature, DecodingError> {
if bytes.len() != SIGNATURE_LENGTH { if bytes.len() != SIGNATURE_LENGTH {
return Err("Wrong length of bytes for signature! Need 64 bytes.") return Err(DecodingError(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(DecodingError(InternalError::ScalarFormatError));
} }
let lower: &[u8; 32] = array_ref!(bytes, 0, 32); Ok(Signature{ r: CompressedEdwardsY(lower), s: Scalar::from_bits(upper) })
let upper: &[u8; 32] = array_ref!(bytes, 32, 32);
Ok(Signature{ r: CompressedEdwardsY(*lower), s: Scalar(*upper) })
} }
} }
@ -199,8 +215,9 @@ impl SecretKey {
/// # /// #
/// use ed25519_dalek::SecretKey; /// use ed25519_dalek::SecretKey;
/// use ed25519_dalek::SECRET_KEY_LENGTH; /// use ed25519_dalek::SECRET_KEY_LENGTH;
/// use ed25519_dalek::DecodingError;
/// ///
/// # fn doctest() -> Result<SecretKey, &'static str> { /// # fn doctest() -> Result<SecretKey, DecodingError> {
/// let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = [ /// let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = [
/// 157, 097, 177, 157, 239, 253, 090, 096, /// 157, 097, 177, 157, 239, 253, 090, 096,
/// 186, 132, 074, 244, 146, 236, 044, 196, /// 186, 132, 074, 244, 146, 236, 044, 196,
@ -221,13 +238,17 @@ impl SecretKey {
/// # Returns /// # Returns
/// ///
/// A `Result` whose okay value is an EdDSA `SecretKey` or whose error value /// A `Result` whose okay value is an EdDSA `SecretKey` or whose error value
/// is an `&'static str` describing the error that occurred. /// is an `DecodingError` wrapping the internal error that occurred.
#[inline] #[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, &'static str> { pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, DecodingError> {
if bytes.len() != SECRET_KEY_LENGTH { if bytes.len() != SECRET_KEY_LENGTH {
return Err("Wrong length of bytes for creating secret key!"); return Err(DecodingError(InternalError::BytesLengthError{
name: "SecretKey", length: SECRET_KEY_LENGTH }));
} }
Ok(SecretKey(*array_ref!(bytes, 0, SECRET_KEY_LENGTH))) let mut bits: [u8; 32] = [0u8; 32];
bits.copy_from_slice(&bytes[..32]);
Ok(SecretKey(bits))
} }
/// Generate a `SecretKey` from a `csprng`. /// Generate a `SecretKey` from a `csprng`.
@ -428,10 +449,10 @@ impl ExpandedSecretKey {
/// # fn main() { } /// # fn main() { }
/// ``` /// ```
#[inline] #[inline]
pub fn to_bytes(&self) -> [u8; 64] { pub fn to_bytes(&self) -> [u8; EXPANDED_SECRET_KEY_LENGTH] {
let mut bytes: [u8; 64] = [0u8; 64]; let mut bytes: [u8; 64] = [0u8; 64];
bytes[..32].copy_from_slice(&self.key.0[..]); bytes[..32].copy_from_slice(self.key.as_bytes());
bytes[32..].copy_from_slice(&self.nonce[..]); bytes[32..].copy_from_slice(&self.nonce[..]);
bytes bytes
} }
@ -441,7 +462,7 @@ impl ExpandedSecretKey {
/// # Returns /// # Returns
/// ///
/// A `Result` whose okay value is an EdDSA `ExpandedSecretKey` or whose /// A `Result` whose okay value is an EdDSA `ExpandedSecretKey` or whose
/// error value is an `&'static str` describing the error that occurred. /// error value is an `DecodingError` describing the error that occurred.
/// ///
/// # Examples /// # Examples
/// ///
@ -452,9 +473,10 @@ impl ExpandedSecretKey {
/// # /// #
/// use rand::{Rng, OsRng}; /// use rand::{Rng, OsRng};
/// use ed25519_dalek::{SecretKey, ExpandedSecretKey}; /// use ed25519_dalek::{SecretKey, ExpandedSecretKey};
/// use ed25519_dalek::DecodingError;
/// ///
/// # #[cfg(feature = "sha2")] /// # #[cfg(feature = "sha2")]
/// # fn do_test() -> Result<ExpandedSecretKey, &'static str> { /// # fn do_test() -> Result<ExpandedSecretKey, DecodingError> {
/// # /// #
/// let mut csprng: OsRng = OsRng::new().unwrap(); /// let mut csprng: OsRng = OsRng::new().unwrap();
/// let secret_key: SecretKey = SecretKey::generate(&mut csprng); /// let secret_key: SecretKey = SecretKey::generate(&mut csprng);
@ -475,12 +497,19 @@ impl ExpandedSecretKey {
/// # fn main() {} /// # fn main() {}
/// ``` /// ```
#[inline] #[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<ExpandedSecretKey, &'static str> { pub fn from_bytes(bytes: &[u8]) -> Result<ExpandedSecretKey, DecodingError> {
if bytes.len() != 64 { if bytes.len() != EXPANDED_SECRET_KEY_LENGTH {
return Err("Wrong length of bytes for creating expanded secret key!"); return Err(DecodingError(InternalError::BytesLengthError{
name: "ExpandedSecretKey", length: EXPANDED_SECRET_KEY_LENGTH }));
} }
Ok(ExpandedSecretKey{ key: Scalar(*array_ref!(bytes, 0, 32)), let mut lower: [u8; 32] = [0u8; 32];
nonce: *array_ref!(bytes, 32, 32), }) let mut upper: [u8; 32] = [0u8; 32];
lower.copy_from_slice(&bytes[00..32]);
upper.copy_from_slice(&bytes[32..64]);
Ok(ExpandedSecretKey{ key: Scalar::from_bits(lower),
nonce: upper })
} }
/// Construct an `ExpandedSecretKey` from a `SecretKey`, using hash function `D`. /// Construct an `ExpandedSecretKey` from a `SecretKey`, using hash function `D`.
@ -507,26 +536,27 @@ impl ExpandedSecretKey {
/// ``` /// ```
pub fn from_secret_key<D>(secret_key: &SecretKey) -> ExpandedSecretKey pub fn from_secret_key<D>(secret_key: &SecretKey) -> ExpandedSecretKey
where D: Digest<OutputSize = U64> + Default { where D: Digest<OutputSize = U64> + Default {
let mut h: D = D::default(); let mut h: D = D::default();
let mut hash: [u8; 64] = [0u8; 64]; let mut hash: [u8; 64] = [0u8; 64];
let mut expanded_key: Scalar; let mut lower: [u8; 32] = [0u8; 32];
let mut upper: [u8; 32] = [0u8; 32];
h.input(secret_key.as_bytes()); h.input(secret_key.as_bytes());
hash.copy_from_slice(h.fixed_result().as_slice()); hash.copy_from_slice(h.fixed_result().as_slice());
expanded_key = Scalar(*array_ref!(&hash, 0, 32)); lower.copy_from_slice(&hash[00..32]);
expanded_key[0] &= 248; upper.copy_from_slice(&hash[32..64]);
expanded_key[31] &= 63;
expanded_key[31] |= 64;
ExpandedSecretKey{ key: expanded_key, nonce: *array_ref!(&hash, 32, 32) } lower[0] &= 248;
lower[31] &= 63;
lower[31] |= 64;
ExpandedSecretKey{ key: Scalar::from_bits(lower), nonce: upper, }
} }
/// Sign a message with this `ExpandedSecretKey`. /// Sign a message with this `ExpandedSecretKey`.
pub fn sign<D>(&self, message: &[u8], public_key: &PublicKey) -> Signature pub fn sign<D>(&self, message: &[u8], public_key: &PublicKey) -> Signature
where D: Digest<OutputSize = U64> + Default { where D: Digest<OutputSize = U64> + Default {
let mut h: D = D::default(); let mut h: D = D::default();
let mut hash: [u8; 64] = [0u8; 64]; let mut hash: [u8; 64] = [0u8; 64];
let mesg_digest: Scalar; let mesg_digest: Scalar;
@ -538,7 +568,7 @@ impl ExpandedSecretKey {
h.input(&message); h.input(&message);
hash.copy_from_slice(h.fixed_result().as_slice()); hash.copy_from_slice(h.fixed_result().as_slice());
mesg_digest = Scalar::reduce(&hash); mesg_digest = Scalar::from_bytes_mod_order_wide(&hash);
r = &mesg_digest * &constants::ED25519_BASEPOINT_TABLE; r = &mesg_digest * &constants::ED25519_BASEPOINT_TABLE;
@ -548,9 +578,9 @@ impl ExpandedSecretKey {
h.input(&message); h.input(&message);
hash.copy_from_slice(h.fixed_result().as_slice()); hash.copy_from_slice(h.fixed_result().as_slice());
hram_digest = Scalar::reduce(&hash); hram_digest = Scalar::from_bytes_mod_order_wide(&hash);
s = Scalar::multiply_add(&hram_digest, &self.key, &mesg_digest); s = &(&hram_digest * &self.key) + &mesg_digest;
Signature{ r: r.compress(), s: s } Signature{ r: r.compress(), s: s }
} }
@ -622,8 +652,9 @@ impl PublicKey {
/// # /// #
/// use ed25519_dalek::PublicKey; /// use ed25519_dalek::PublicKey;
/// use ed25519_dalek::PUBLIC_KEY_LENGTH; /// use ed25519_dalek::PUBLIC_KEY_LENGTH;
/// use ed25519_dalek::DecodingError;
/// ///
/// # fn doctest() -> Result<PublicKey, &'static str> { /// # fn doctest() -> Result<PublicKey, DecodingError> {
/// let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = [ /// let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = [
/// 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58, /// 215, 90, 152, 1, 130, 177, 10, 183, 213, 75, 254, 211, 201, 100, 7, 58,
/// 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26]; /// 14, 225, 114, 243, 218, 166, 35, 37, 175, 2, 26, 104, 247, 7, 81, 26];
@ -641,13 +672,17 @@ impl PublicKey {
/// # Returns /// # Returns
/// ///
/// A `Result` whose okay value is an EdDSA `PublicKey` or whose error value /// A `Result` whose okay value is an EdDSA `PublicKey` or whose error value
/// is an `&'static str` describing the error that occurred. /// is an `DecodingError` describing the error that occurred.
#[inline] #[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, &'static str> { pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, DecodingError> {
if bytes.len() != PUBLIC_KEY_LENGTH { if bytes.len() != PUBLIC_KEY_LENGTH {
return Err("Wrong length of bytes for creating public key!"); return Err(DecodingError(InternalError::BytesLengthError{
name: "PublicKey", length: PUBLIC_KEY_LENGTH }));
} }
Ok(PublicKey(CompressedEdwardsY(*array_ref!(bytes, 0, 32)))) let mut bits: [u8; 32] = [0u8; 32];
bits.copy_from_slice(&bytes[..32]);
Ok(PublicKey(CompressedEdwardsY(bits)))
} }
/// Convert this public key to its underlying extended twisted Edwards coordinate. /// Convert this public key to its underlying extended twisted Edwards coordinate.
@ -657,25 +692,24 @@ impl PublicKey {
} }
/// Derive this public key from its corresponding `SecretKey`. /// Derive this public key from its corresponding `SecretKey`.
#[cfg(feature = "std")]
#[allow(unused_assignments)] #[allow(unused_assignments)]
pub fn from_secret<D>(secret_key: &SecretKey) -> PublicKey pub fn from_secret<D>(secret_key: &SecretKey) -> PublicKey
where D: Digest<OutputSize = U64> + Default { where D: Digest<OutputSize = U64> + Default {
let mut h: D = D::default(); let mut h: D = D::default();
let mut hash: [u8; 64] = [0u8; 64]; let mut hash: [u8; 64] = [0u8; 64];
let pk: [u8; 32]; let mut digest: [u8; 32] = [0u8; 32];
let mut digest: &mut [u8; 32]; let pk: [u8; 32];
h.input(secret_key.as_bytes()); h.input(secret_key.as_bytes());
hash.copy_from_slice(h.fixed_result().as_slice()); hash.copy_from_slice(h.fixed_result().as_slice());
digest = array_mut_ref!(&mut hash, 0, 32); digest.copy_from_slice(&hash[..32]);
digest[0] &= 248; digest[0] &= 248;
digest[31] &= 127; digest[31] &= 127;
digest[31] |= 64; digest[31] |= 64;
pk = (&Scalar(*digest) * &constants::ED25519_BASEPOINT_TABLE).compress().to_bytes(); pk = (&Scalar::from_bits(digest) * &constants::ED25519_BASEPOINT_TABLE).compress().to_bytes();
PublicKey(CompressedEdwardsY(pk)) PublicKey(CompressedEdwardsY(pk))
} }
@ -687,20 +721,15 @@ impl PublicKey {
/// Returns true if the signature was successfully verified, and /// Returns true if the signature was successfully verified, and
/// false otherwise. /// false otherwise.
pub fn verify<D>(&self, message: &[u8], signature: &Signature) -> bool pub fn verify<D>(&self, message: &[u8], signature: &Signature) -> bool
where D: Digest<OutputSize = U64> + Default { where D: Digest<OutputSize = U64> + Default
{
use curve25519_dalek::edwards::vartime; use curve25519_dalek::edwards::vartime;
let mut h: D = D::default(); let mut h: D = D::default();
let mut a: ExtendedPoint; let mut a: ExtendedPoint;
let ao: Option<ExtendedPoint>; let ao: Option<ExtendedPoint>;
let r: ExtendedPoint; let mut digest: [u8; 64] = [0u8; 64];
let digest: [u8; 64];
let digest_reduced: Scalar;
if signature.s[31] & 224 != 0 {
return false;
}
ao = self.decompress(); ao = self.decompress();
if ao.is_some() { if ao.is_some() {
@ -714,10 +743,10 @@ impl PublicKey {
h.input(self.as_bytes()); h.input(self.as_bytes());
h.input(&message); h.input(&message);
let digest_bytes = h.fixed_result(); digest.copy_from_slice(h.fixed_result().as_slice());
digest = *array_ref!(digest_bytes, 0, 64);
digest_reduced = Scalar::reduce(&digest); let digest_reduced: Scalar = Scalar::from_bytes_mod_order_wide(&digest);
r = vartime::double_scalar_mult_basepoint(&digest_reduced, &a, &signature.s); let r: ExtendedPoint = vartime::double_scalar_mult_basepoint(&digest_reduced, &a, &signature.s);
slices_equal(signature.r.as_bytes(), r.compress().as_bytes()) == 1 slices_equal(signature.r.as_bytes(), r.compress().as_bytes()) == 1
} }
@ -740,7 +769,7 @@ impl<'d> Deserialize<'d> for PublicKey {
type Value = PublicKey; type Value = PublicKey;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
formatter.write_str("An ed25519 signature as specified in RFC8032") formatter.write_str("An ed25519 public key as a 32-byte compressed point, as specified in RFC8032")
} }
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<PublicKey, E> where E: SerdeError { fn visit_bytes<E>(self, bytes: &[u8]) -> Result<PublicKey, E> where E: SerdeError {
@ -753,6 +782,7 @@ impl<'d> Deserialize<'d> for PublicKey {
/// An ed25519 keypair. /// An ed25519 keypair.
#[derive(Debug)] #[derive(Debug)]
#[repr(C)]
pub struct Keypair { pub struct Keypair {
/// The secret half of this keypair. /// The secret half of this keypair.
pub secret: SecretKey, pub secret: SecretKey,
@ -796,10 +826,11 @@ impl Keypair {
/// # Returns /// # Returns
/// ///
/// A `Result` whose okay value is an EdDSA `Keypair` or whose error value /// A `Result` whose okay value is an EdDSA `Keypair` or whose error value
/// is an `&'static str` describing the error that occurred. /// is an `DecodingError` describing the error that occurred.
pub fn from_bytes<'a>(bytes: &'a [u8]) -> Result<Keypair, &'static str> { pub fn from_bytes<'a>(bytes: &'a [u8]) -> Result<Keypair, DecodingError> {
if bytes.len() != KEYPAIR_LENGTH { if bytes.len() != KEYPAIR_LENGTH {
return Err("Wrong length of bytes for creating keypair!"); return Err(DecodingError(InternalError::BytesLengthError{
name: "Keypair", length: KEYPAIR_LENGTH}));
} }
let secret = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH])?; let secret = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH])?;
let public = PublicKey::from_bytes(&bytes[SECRET_KEY_LENGTH..])?; let public = PublicKey::from_bytes(&bytes[SECRET_KEY_LENGTH..])?;
@ -850,13 +881,14 @@ impl Keypair {
} }
/// Sign a message with this keypair's secret key. /// Sign a message with this keypair's secret key.
pub fn sign<D>(&self, message: &[u8]) -> Signature where D: Digest<OutputSize = U64> + Default { pub fn sign<D>(&self, message: &[u8]) -> Signature
where D: Digest<OutputSize = U64> + Default {
self.secret.expand::<D>().sign::<D>(&message, &self.public) self.secret.expand::<D>().sign::<D>(&message, &self.public)
} }
/// Verify a signature on a message with this keypair's public key. /// Verify a signature on a message with this keypair's public key.
pub fn verify<D>(&self, message: &[u8], signature: &Signature) -> bool pub fn verify<D>(&self, message: &[u8], signature: &Signature) -> bool
where D: FixedOutput<OutputSize = U64> + BlockInput + Default + Input { where D: Digest<OutputSize = U64> + Default {
self.public.verify::<D>(message, signature) self.public.verify::<D>(message, signature)
} }
} }
@ -1032,7 +1064,7 @@ mod test {
#[test] #[test]
fn public_key_from_bytes() { fn public_key_from_bytes() {
// Make another function so that we can test the ? operator. // Make another function so that we can test the ? operator.
fn do_the_test() -> Result<PublicKey, &'static str> { fn do_the_test() -> Result<PublicKey, DecodingError> {
let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = [ let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = [
215, 090, 152, 001, 130, 177, 010, 183, 215, 090, 152, 001, 130, 177, 010, 183,
213, 075, 254, 211, 201, 100, 007, 058, 213, 075, 254, 211, 201, 100, 007, 058,
@ -1149,10 +1181,11 @@ mod bench {
fn underlying_scalar_mult_basepoint(b: &mut Bencher) { fn underlying_scalar_mult_basepoint(b: &mut Bencher) {
use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE; use curve25519_dalek::constants::ED25519_BASEPOINT_TABLE;
let scalar: Scalar = Scalar([ 20, 130, 129, 196, 247, 182, 211, 102, let scalar: Scalar = Scalar::from_bits([
11, 168, 169, 131, 159, 69, 126, 35, 20, 130, 129, 196, 247, 182, 211, 102,
109, 193, 175, 54, 118, 234, 138, 81, 11, 168, 169, 131, 159, 69, 126, 35,
60, 183, 80, 186, 92, 248, 132, 13, ]); 109, 193, 175, 54, 118, 234, 138, 81,
60, 183, 80, 186, 92, 248, 132, 13, ]);
b.iter(| | &scalar * &ED25519_BASEPOINT_TABLE); b.iter(| | &scalar * &ED25519_BASEPOINT_TABLE);
} }

82
src/errors.rs Normal file
View file

@ -0,0 +1,82 @@
// -*- mode: rust; -*-
//
// This file is part of ed25519-dalek.
// Copyright (c) 2017 Isis Lovecruft
// See LICENSE for licensing information.
//
// Authors:
// - Isis Agora Lovecruft <isis@patternsinthevoid.net>
//! Errors which may occur when parsing keys and/or signatures to or from wire formats.
// rustc seems to think the typenames in match statements (e.g. in
// Display) should be snake cased, for some reason.
#![allow(non_snake_case)]
use core::fmt;
use core::fmt::Display;
/// Internal errors. Most application-level developer will likely not
/// need to pay any attention to these.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub (crate) enum InternalError {
PointDecompressionError,
ScalarFormatError,
/// An error in the length of bytes handed to a constructor.
///
/// To use this, pass a string specifying the `name` of the type which is
/// returning the error, and the `length` in bytes which its constructor
/// expects.
BytesLengthError{ name: &'static str, length: usize },
}
impl Display for InternalError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
InternalError::PointDecompressionError
=> write!(f, "Cannot decompress extended twisted edwards point"),
InternalError::ScalarFormatError
=> write!(f, "Cannot use scalar with high-bit set"),
InternalError::BytesLengthError{ name: n, length: l}
=> write!(f, "{} must be {} bytes in length", n, l),
}
}
}
impl ::failure::Fail for InternalError {}
/// Errors which may occur in the `from_bytes()` constructors of `PublicKey`,
/// `SecretKey`, `ExpandedSecretKey`, `Keypair`, and `Signature`.
///
/// There was an internal problem due to parsing the `Signature`.
///
/// This error may arise due to:
///
/// * A problem decompressing `r`, a curve point, in the `Signature`, or the
/// curve point for a `PublicKey`.
/// * A problem with the format of `s`, a scalar, in the `Signature`. This
/// is only raised if the high-bit of the scalar was set. (Scalars must
/// only be constructed from 255-bit integers.)
/// * Being given bytes with a length different to what was expected.
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub struct DecodingError(pub (crate) InternalError);
impl Display for DecodingError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
InternalError::PointDecompressionError => write!(f, "{}", self.0),
InternalError::ScalarFormatError => write!(f, "{}", self.0),
InternalError::BytesLengthError{ name: _, length: _ } => write!(f, "{}", self.0),
}
}
}
impl ::failure::Fail for DecodingError {
fn cause(&self) -> Option<&::failure::Fail> {
match self.0 {
InternalError::PointDecompressionError => Some(&self.0),
InternalError::ScalarFormatError => Some(&self.0),
InternalError::BytesLengthError{ name: _, length: _} => Some(&self.0),
}
}
}

View file

@ -143,9 +143,9 @@
//! # extern crate ed25519_dalek; //! # extern crate ed25519_dalek;
//! # use rand::{Rng, OsRng}; //! # use rand::{Rng, OsRng};
//! # use sha2::Sha512; //! # use sha2::Sha512;
//! # use ed25519_dalek::{Keypair, Signature, PublicKey, SecretKey}; //! # use ed25519_dalek::{Keypair, Signature, PublicKey, SecretKey, DecodingError};
//! # use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH}; //! # use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};
//! # fn do_test() -> Result<(SecretKey, PublicKey, Keypair, Signature), &'static str> { //! # fn do_test() -> Result<(SecretKey, PublicKey, Keypair, Signature), DecodingError> {
//! # let mut cspring: OsRng = OsRng::new().unwrap(); //! # let mut cspring: OsRng = OsRng::new().unwrap();
//! # let keypair_orig: Keypair = Keypair::generate::<Sha512>(&mut cspring); //! # let keypair_orig: Keypair = Keypair::generate::<Sha512>(&mut cspring);
//! # let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes(); //! # let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
@ -257,17 +257,16 @@
#![allow(unused_features)] #![allow(unused_features)]
#![deny(missing_docs)] // refuse to compile if documentation is missing #![deny(missing_docs)] // refuse to compile if documentation is missing
#[macro_use]
extern crate arrayref;
extern crate curve25519_dalek; extern crate curve25519_dalek;
extern crate generic_array; extern crate generic_array;
extern crate digest; extern crate digest;
extern crate subtle; extern crate subtle;
extern crate failure;
#[cfg(feature = "std")] #[cfg(feature = "std")]
extern crate rand; extern crate rand;
#[cfg(test)] #[cfg(any(feature = "std", test))]
#[macro_use] #[macro_use]
extern crate std; extern crate std;
@ -288,5 +287,8 @@ extern crate bincode;
mod ed25519; mod ed25519;
pub mod errors;
// Export everything public in ed25519. // Export everything public in ed25519.
pub use ed25519::*; pub use ed25519::*;
pub use errors::*;