Merge remote-tracking branch 'hdevalence/verify-result' into develop

This commit is contained in:
Isis Lovecruft 2018-07-15 21:21:14 +00:00
commit 3840cb9733
Failed to extract signature
5 changed files with 86 additions and 153 deletions

View file

@ -19,10 +19,6 @@ travis-ci = { repository = "dalek-cryptography/ed25519-dalek", branch = "master"
version = "0.18" version = "0.18"
default-features = false default-features = false
[dependencies.subtle]
version = "0.6"
default-features = false
[dependencies.rand] [dependencies.rand]
version = "0.5" version = "0.5"
default-features = false default-features = false
@ -59,8 +55,8 @@ harness = false
[features] [features]
default = ["std", "u64_backend"] default = ["std", "u64_backend"]
# We don't add "rand/std" here because it would enable a bunch of Fuchsia dependencies. # We don't add "rand/std" here because it would enable a bunch of Fuchsia dependencies.
std = ["subtle/std", "curve25519-dalek/std"] std = ["curve25519-dalek/std"]
nightly = ["curve25519-dalek/nightly", "subtle/nightly", "rand/nightly"] nightly = ["curve25519-dalek/nightly", "rand/nightly"]
asm = ["sha2/asm"] asm = ["sha2/asm"]
yolocrypto = ["curve25519-dalek/yolocrypto"] yolocrypto = ["curve25519-dalek/yolocrypto"]
u64_backend = ["curve25519-dalek/u64_backend"] u64_backend = ["curve25519-dalek/u64_backend"]

View file

@ -55,12 +55,9 @@ nanoseconds to cycles per second on a 2591 Mhz CPU, that's 237660 cycles for
verification and 102523 for signing, which for signing is competitive verification and 102523 for signing, which for signing is competitive
with optimised assembly versions. with optimised assembly versions.
Additionally, if you're on the Rust nightly channel, be sure to build with Additionally, if you're using a CSPRNG from the `rand` crate, the `nightly`
`cargo build --features="nightly"` which enables more secure compiler feature will enable `u128`/`i128` features there, resulting in potentially
optimisation protections in the faster performance.
[subtle](https://github.com/dalek-cryptography/subtle) crate. Additionally, if
you're using a CSPRNG from the `rand` crate, the `nightly` feature will enable
`u128`/`i128` features there, resulting in potentially faster performance.
Additionally, thanks to Rust, this implementation has both type and memory Additionally, thanks to Rust, this implementation has both type and memory
safety. It's also easily readable by a much larger set of people than those who safety. It's also easily readable by a much larger set of people than those who

View file

@ -36,9 +36,7 @@ use curve25519_dalek::edwards::CompressedEdwardsY;
use curve25519_dalek::edwards::EdwardsPoint; use curve25519_dalek::edwards::EdwardsPoint;
use curve25519_dalek::scalar::Scalar; use curve25519_dalek::scalar::Scalar;
use subtle::ConstantTimeEq; use errors::SignatureError;
use errors::DecodingError;
use errors::InternalError; use errors::InternalError;
/// The length of a curve25519 EdDSA `Signature`, in bytes. /// The length of a curve25519 EdDSA `Signature`, in bytes.
@ -132,9 +130,9 @@ 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, DecodingError> { pub fn from_bytes(bytes: &[u8]) -> Result<Signature, SignatureError> {
if bytes.len() != SIGNATURE_LENGTH { if bytes.len() != SIGNATURE_LENGTH {
return Err(DecodingError(InternalError::BytesLengthError{ return Err(SignatureError(InternalError::BytesLengthError{
name: "Signature", length: SIGNATURE_LENGTH })); name: "Signature", length: SIGNATURE_LENGTH }));
} }
let mut lower: [u8; 32] = [0u8; 32]; let mut lower: [u8; 32] = [0u8; 32];
@ -144,7 +142,7 @@ impl Signature {
upper.copy_from_slice(&bytes[32..]); upper.copy_from_slice(&bytes[32..]);
if upper[31] & 224 != 0 { if upper[31] & 224 != 0 {
return Err(DecodingError(InternalError::ScalarFormatError)); return Err(SignatureError(InternalError::ScalarFormatError));
} }
Ok(Signature{ r: CompressedEdwardsY(lower), s: Scalar::from_bits(upper) }) Ok(Signature{ r: CompressedEdwardsY(lower), s: Scalar::from_bits(upper) })
@ -215,9 +213,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; /// use ed25519_dalek::SignatureError;
/// ///
/// # fn doctest() -> Result<SecretKey, DecodingError> { /// # fn doctest() -> Result<SecretKey, SignatureError> {
/// 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,
@ -238,11 +236,11 @@ 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 `DecodingError` wrapping the internal error that occurred. /// is an `SignatureError` wrapping the internal error that occurred.
#[inline] #[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, DecodingError> { pub fn from_bytes(bytes: &[u8]) -> Result<SecretKey, SignatureError> {
if bytes.len() != SECRET_KEY_LENGTH { if bytes.len() != SECRET_KEY_LENGTH {
return Err(DecodingError(InternalError::BytesLengthError{ return Err(SignatureError(InternalError::BytesLengthError{
name: "SecretKey", length: SECRET_KEY_LENGTH })); name: "SecretKey", length: SECRET_KEY_LENGTH }));
} }
let mut bits: [u8; 32] = [0u8; 32]; let mut bits: [u8; 32] = [0u8; 32];
@ -469,7 +467,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 `DecodingError` describing the error that occurred. /// error value is an `SignatureError` describing the error that occurred.
/// ///
/// # Examples /// # Examples
/// ///
@ -479,11 +477,11 @@ impl ExpandedSecretKey {
/// # extern crate ed25519_dalek; /// # extern crate ed25519_dalek;
/// # /// #
/// # #[cfg(all(feature = "sha2", feature = "std"))] /// # #[cfg(all(feature = "sha2", feature = "std"))]
/// # fn do_test() -> Result<ExpandedSecretKey, DecodingError> { /// # fn do_test() -> Result<ExpandedSecretKey, SignatureError> {
/// # /// #
/// use rand::{Rng, OsRng}; /// use rand::{Rng, OsRng};
/// use ed25519_dalek::{SecretKey, ExpandedSecretKey}; /// use ed25519_dalek::{SecretKey, ExpandedSecretKey};
/// use ed25519_dalek::DecodingError; /// use ed25519_dalek::SignatureError;
/// ///
/// 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);
@ -504,9 +502,9 @@ impl ExpandedSecretKey {
/// # fn main() { } /// # fn main() { }
/// ``` /// ```
#[inline] #[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<ExpandedSecretKey, DecodingError> { pub fn from_bytes(bytes: &[u8]) -> Result<ExpandedSecretKey, SignatureError> {
if bytes.len() != EXPANDED_SECRET_KEY_LENGTH { if bytes.len() != EXPANDED_SECRET_KEY_LENGTH {
return Err(DecodingError(InternalError::BytesLengthError{ return Err(SignatureError(InternalError::BytesLengthError{
name: "ExpandedSecretKey", length: EXPANDED_SECRET_KEY_LENGTH })); name: "ExpandedSecretKey", length: EXPANDED_SECRET_KEY_LENGTH }));
} }
let mut lower: [u8; 32] = [0u8; 32]; let mut lower: [u8; 32] = [0u8; 32];
@ -746,9 +744,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; /// use ed25519_dalek::SignatureError;
/// ///
/// # fn doctest() -> Result<PublicKey, DecodingError> { /// # fn doctest() -> Result<PublicKey, SignatureError> {
/// 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];
@ -766,11 +764,11 @@ 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 `DecodingError` describing the error that occurred. /// is an `SignatureError` describing the error that occurred.
#[inline] #[inline]
pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, DecodingError> { pub fn from_bytes(bytes: &[u8]) -> Result<PublicKey, SignatureError> {
if bytes.len() != PUBLIC_KEY_LENGTH { if bytes.len() != PUBLIC_KEY_LENGTH {
return Err(DecodingError(InternalError::BytesLengthError{ return Err(SignatureError(InternalError::BytesLengthError{
name: "PublicKey", length: PUBLIC_KEY_LENGTH })); name: "PublicKey", length: PUBLIC_KEY_LENGTH }));
} }
let mut bits: [u8; 32] = [0u8; 32]; let mut bits: [u8; 32] = [0u8; 32];
@ -779,12 +777,6 @@ impl PublicKey {
Ok(PublicKey(CompressedEdwardsY(bits))) Ok(PublicKey(CompressedEdwardsY(bits)))
} }
/// Convert this public key to its underlying extended twisted Edwards coordinate.
#[inline]
fn decompress(&self) -> Option<EdwardsPoint> {
self.0.decompress()
}
/// Derive this public key from its corresponding `SecretKey`. /// Derive this public key from its corresponding `SecretKey`.
#[allow(unused_assignments)] #[allow(unused_assignments)]
pub fn from_secret<D>(secret_key: &SecretKey) -> PublicKey pub fn from_secret<D>(secret_key: &SecretKey) -> PublicKey
@ -812,36 +804,27 @@ impl PublicKey {
/// ///
/// # Return /// # Return
/// ///
/// Returns true if the signature was successfully verified, and /// Returns `Ok(())` if the signature is valid, and `Err` otherwise.
/// false otherwise. #[allow(non_snake_case)]
pub fn verify<D>(&self, message: &[u8], signature: &Signature) -> bool pub fn verify<D>(&self, message: &[u8], signature: &Signature) -> Result<(), SignatureError>
where D: Digest<OutputSize = U64> + Default where D: Digest<OutputSize = U64> + Default
{ {
let mut h: D = D::default(); let A = self.0.decompress()
let mut a: EdwardsPoint; .ok_or_else(|| SignatureError(InternalError::PointDecompressionError))?;
let ao: Option<EdwardsPoint>;
let mut digest: [u8; 64] = [0u8; 64];
ao = self.decompress();
if ao.is_some() {
a = ao.unwrap();
} else {
return false;
}
a = -(&a);
let mut h = D::default();
h.input(signature.r.as_bytes()); h.input(signature.r.as_bytes());
h.input(self.as_bytes()); h.input(self.as_bytes());
h.input(&message); h.input(&message);
let k = Scalar::from_hash(h);
digest.copy_from_slice(h.fixed_result().as_slice()); let R = EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(-A), &signature.s);
let digest_reduced: Scalar = Scalar::from_bytes_mod_order_wide(&digest); if R.compress() == signature.r {
let r: EdwardsPoint = EdwardsPoint::vartime_double_scalar_mul_basepoint(&digest_reduced, Ok(())
&a, &signature.s); } else {
Err(SignatureError(InternalError::VerifyError))
(signature.r.as_bytes()).ct_eq(r.compress().as_bytes()).unwrap_u8() == 1 }
} }
/// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm. /// Verify a `signature` on a `prehashed_message` using the Ed25519ph algorithm.
@ -862,43 +845,36 @@ impl PublicKey {
/// `Keypair` on the `prehashed_message`. /// `Keypair` on the `prehashed_message`.
/// ///
/// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1 /// [rfc8032]: https://tools.ietf.org/html/rfc8032#section-5.1
#[allow(non_snake_case)]
pub fn verify_prehashed<D>(&self, pub fn verify_prehashed<D>(&self,
prehashed_message: D, prehashed_message: D,
context: Option<&[u8]>, context: Option<&[u8]>,
signature: &Signature) -> bool signature: &Signature) -> Result<(), SignatureError>
where D: Digest<OutputSize = U64> + Default where D: Digest<OutputSize = U64> + Default
{ {
let mut h: D = D::default(); let ctx = context.unwrap_or(b"");
let mut hash: [u8; 64] = [0u8; 64];
let mut a: EdwardsPoint = match self.decompress() {
Some(x) => x,
None => return false,
};
a = -(&a);
let ctx: &[u8] = match context {
Some(x) => x,
None => b"", // By default, the context is an empty string.
};
debug_assert!(ctx.len() <= 255, "The context must not be longer than 255 octets."); debug_assert!(ctx.len() <= 255, "The context must not be longer than 255 octets.");
let ctx_len: u8 = ctx.len() as u8; let A = self.0.decompress()
.ok_or_else(|| SignatureError(InternalError::PointDecompressionError))?;
let mut h = D::default();
h.input(b"SigEd25519 no Ed25519 collisions"); h.input(b"SigEd25519 no Ed25519 collisions");
h.input(&[1]); // Ed25519ph h.input(&[1]); // Ed25519ph
h.input(&[ctx_len]); h.input(&[ctx.len() as u8]);
h.input(ctx); h.input(ctx);
h.input(signature.r.as_bytes()); h.input(signature.r.as_bytes());
h.input(self.as_bytes()); h.input(self.as_bytes());
h.input(prehashed_message.fixed_result().as_slice()); h.input(prehashed_message.fixed_result().as_slice());
hash.copy_from_slice(h.fixed_result().as_slice()); let k = Scalar::from_hash(h);
let digest_reduced: Scalar = Scalar::from_bytes_mod_order_wide(&hash); let R = EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &(-A), &signature.s);
let r: EdwardsPoint = EdwardsPoint::vartime_double_scalar_mul_basepoint(&digest_reduced,
&a, &signature.s);
(signature.r.as_bytes()).ct_eq(r.compress().as_bytes()).unwrap_u8() == 1 if R.compress() == signature.r {
Ok(())
} else {
Err(SignatureError(InternalError::VerifyError))
}
} }
} }
@ -976,10 +952,10 @@ 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 `DecodingError` describing the error that occurred. /// is an `SignatureError` describing the error that occurred.
pub fn from_bytes<'a>(bytes: &'a [u8]) -> Result<Keypair, DecodingError> { pub fn from_bytes<'a>(bytes: &'a [u8]) -> Result<Keypair, SignatureError> {
if bytes.len() != KEYPAIR_LENGTH { if bytes.len() != KEYPAIR_LENGTH {
return Err(DecodingError(InternalError::BytesLengthError{ return Err(SignatureError(InternalError::BytesLengthError{
name: "Keypair", length: KEYPAIR_LENGTH})); name: "Keypair", length: KEYPAIR_LENGTH}));
} }
let secret = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH])?; let secret = SecretKey::from_bytes(&bytes[..SECRET_KEY_LENGTH])?;
@ -1145,7 +1121,7 @@ impl Keypair {
} }
/// 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) -> Result<(), SignatureError>
where D: Digest<OutputSize = U64> + Default { where D: Digest<OutputSize = U64> + Default {
self.public.verify::<D>(message, signature) self.public.verify::<D>(message, signature)
} }
@ -1210,7 +1186,7 @@ impl Keypair {
pub fn verify_prehashed<D>(&self, pub fn verify_prehashed<D>(&self,
prehashed_message: D, prehashed_message: D,
context: Option<&[u8]>, context: Option<&[u8]>,
signature: &Signature) -> bool signature: &Signature) -> Result<(), SignatureError>
where D: Digest<OutputSize = U64> + Default where D: Digest<OutputSize = U64> + Default
{ {
self.public.verify_prehashed::<D>(prehashed_message, context, signature) self.public.verify_prehashed::<D>(prehashed_message, context, signature)
@ -1261,7 +1237,6 @@ mod test {
use std::fs::File; use std::fs::File;
use std::string::String; use std::string::String;
use std::vec::Vec; use std::vec::Vec;
use curve25519_dalek::edwards::EdwardsPoint;
use rand::ChaChaRng; use rand::ChaChaRng;
use rand::SeedableRng; use rand::SeedableRng;
use hex::FromHex; use hex::FromHex;
@ -1295,32 +1270,7 @@ mod test {
063, 120, 126, 100, 092, 059, 050, 011, ]; 063, 120, 126, 100, 092, 059, 050, 011, ];
#[test] #[test]
fn unmarshal_marshal() { // TestUnmarshalMarshal fn sign_verify() { // TestSignVerify
let mut csprng: ChaChaRng;
let mut keypair: Keypair;
let mut x: Option<EdwardsPoint>;
let a: EdwardsPoint;
let public: PublicKey;
csprng = ChaChaRng::from_seed([0u8; 32]);
// from_bytes() fails if vx²-u=0 and vx²+u=0
loop {
keypair = Keypair::generate::<Sha512, _>(&mut csprng);
x = keypair.public.decompress();
if x.is_some() {
a = x.unwrap();
break;
}
}
public = PublicKey(a.compress());
assert!(keypair.public.0 == public.0);
}
#[test]
fn ed25519_sign_verify() { // TestSignVerify
let mut csprng: ChaChaRng; let mut csprng: ChaChaRng;
let keypair: Keypair; let keypair: Keypair;
let good_sig: Signature; let good_sig: Signature;
@ -1334,11 +1284,11 @@ mod test {
good_sig = keypair.sign::<Sha512>(&good); good_sig = keypair.sign::<Sha512>(&good);
bad_sig = keypair.sign::<Sha512>(&bad); bad_sig = keypair.sign::<Sha512>(&bad);
assert!(keypair.verify::<Sha512>(&good, &good_sig) == true, assert!(keypair.verify::<Sha512>(&good, &good_sig).is_ok(),
"Verification of a valid signature failed!"); "Verification of a valid signature failed!");
assert!(keypair.verify::<Sha512>(&good, &bad_sig) == false, assert!(keypair.verify::<Sha512>(&good, &bad_sig).is_err(),
"Verification of a signature on a different message passed!"); "Verification of a signature on a different message passed!");
assert!(keypair.verify::<Sha512>(&bad, &good_sig) == false, assert!(keypair.verify::<Sha512>(&bad, &good_sig).is_err(),
"Verification of a signature on a different message passed!"); "Verification of a signature on a different message passed!");
} }
@ -1383,7 +1333,7 @@ mod test {
let sig2: Signature = keypair.sign::<Sha512>(&msg_bytes); let sig2: Signature = keypair.sign::<Sha512>(&msg_bytes);
assert!(sig1 == sig2, "Signature bytes not equal on line {}", lineno); assert!(sig1 == sig2, "Signature bytes not equal on line {}", lineno);
assert!(keypair.verify::<Sha512>(&msg_bytes, &sig2), assert!(keypair.verify::<Sha512>(&msg_bytes, &sig2).is_ok(),
"Signature verification failed on line {}", lineno); "Signature verification failed on line {}", lineno);
} }
} }
@ -1417,7 +1367,7 @@ mod test {
assert!(sig1 == sig2, assert!(sig1 == sig2,
"Original signature from test vectors doesn't equal signature produced:\ "Original signature from test vectors doesn't equal signature produced:\
\noriginal:\n{:?}\nproduced:\n{:?}", sig1, sig2); \noriginal:\n{:?}\nproduced:\n{:?}", sig1, sig2);
assert!(keypair.verify_prehashed(prehash_for_verifying, None, &sig2), assert!(keypair.verify_prehashed(prehash_for_verifying, None, &sig2).is_ok(),
"Could not verify ed25519ph signature!"); "Could not verify ed25519ph signature!");
} }
@ -1451,18 +1401,18 @@ mod test {
good_sig = keypair.sign_prehashed::<Sha512>(prehashed_good1, Some(context)); good_sig = keypair.sign_prehashed::<Sha512>(prehashed_good1, Some(context));
bad_sig = keypair.sign_prehashed::<Sha512>(prehashed_bad1, Some(context)); bad_sig = keypair.sign_prehashed::<Sha512>(prehashed_bad1, Some(context));
assert!(keypair.verify_prehashed::<Sha512>(prehashed_good2, Some(context), &good_sig) == true, assert!(keypair.verify_prehashed::<Sha512>(prehashed_good2, Some(context), &good_sig).is_ok(),
"Verification of a valid signature failed!"); "Verification of a valid signature failed!");
assert!(keypair.verify_prehashed::<Sha512>(prehashed_good3, Some(context), &bad_sig) == false, assert!(keypair.verify_prehashed::<Sha512>(prehashed_good3, Some(context), &bad_sig).is_err(),
"Verification of a signature on a different message passed!"); "Verification of a signature on a different message passed!");
assert!(keypair.verify_prehashed::<Sha512>(prehashed_bad2, Some(context), &good_sig) == false, assert!(keypair.verify_prehashed::<Sha512>(prehashed_bad2, Some(context), &good_sig).is_err(),
"Verification of a signature on a different message passed!"); "Verification of a signature on a different message passed!");
} }
#[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, DecodingError> { fn do_the_test() -> Result<PublicKey, SignatureError> {
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,

View file

@ -20,7 +20,6 @@ use core::fmt::Display;
/// need to pay any attention to these. /// need to pay any attention to these.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub (crate) enum InternalError { pub (crate) enum InternalError {
#[allow(dead_code)]
PointDecompressionError, PointDecompressionError,
ScalarFormatError, ScalarFormatError,
/// An error in the length of bytes handed to a constructor. /// An error in the length of bytes handed to a constructor.
@ -29,55 +28,52 @@ pub (crate) enum InternalError {
/// returning the error, and the `length` in bytes which its constructor /// returning the error, and the `length` in bytes which its constructor
/// expects. /// expects.
BytesLengthError{ name: &'static str, length: usize }, BytesLengthError{ name: &'static str, length: usize },
/// The verification equation wasn't satisfied
VerifyError,
} }
impl Display for InternalError { impl Display for InternalError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
InternalError::PointDecompressionError InternalError::PointDecompressionError
=> write!(f, "Cannot decompress extended twisted edwards point"), => write!(f, "Cannot decompress Edwards point"),
InternalError::ScalarFormatError InternalError::ScalarFormatError
=> write!(f, "Cannot use scalar with high-bit set"), => write!(f, "Cannot use scalar with high-bit set"),
InternalError::BytesLengthError{ name: n, length: l} InternalError::BytesLengthError{ name: n, length: l}
=> write!(f, "{} must be {} bytes in length", n, l), => write!(f, "{} must be {} bytes in length", n, l),
InternalError::VerifyError
=> write!(f, "Verification equation was not satisfied"),
} }
} }
} }
impl ::failure::Fail for InternalError {} impl ::failure::Fail for InternalError {}
/// Errors which may occur in the `from_bytes()` constructors of `PublicKey`, /// Errors which may occur while processing signatures and keypairs.
/// `SecretKey`, `ExpandedSecretKey`, `Keypair`, and `Signature`.
///
/// There was an internal problem due to parsing the `Signature`.
/// ///
/// This error may arise due to: /// This error may arise due to:
/// ///
/// * Being given bytes with a length different to what was expected.
///
/// * A problem decompressing `r`, a curve point, in the `Signature`, or the /// * A problem decompressing `r`, a curve point, in the `Signature`, or the
/// curve point for a `PublicKey`. /// curve point for a `PublicKey`.
///
/// * A problem with the format of `s`, a scalar, in the `Signature`. This /// * 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 /// is only raised if the high-bit of the scalar was set. (Scalars must
/// only be constructed from 255-bit integers.) /// only be constructed from 255-bit integers.)
/// * Being given bytes with a length different to what was expected. ///
/// * Failure of a signature to satisfy the verification equation.
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub struct DecodingError(pub (crate) InternalError); pub struct SignatureError(pub (crate) InternalError);
impl Display for DecodingError { impl Display for SignatureError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 { write!(f, "{}", 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 { impl ::failure::Fail for SignatureError {
fn cause(&self) -> Option<&::failure::Fail> { fn cause(&self) -> Option<&::failure::Fail> {
match self.0 { Some(&self.0)
InternalError::PointDecompressionError => Some(&self.0),
InternalError::ScalarFormatError => Some(&self.0),
InternalError::BytesLengthError{ name: _, length: _} => Some(&self.0),
}
} }
} }

View file

@ -78,9 +78,7 @@
//! # let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng); //! # let keypair: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
//! # 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();
//! # let signature: Signature = keypair.sign::<Sha512>(message); //! # let signature: Signature = keypair.sign::<Sha512>(message);
//! let verified: bool = keypair.verify::<Sha512>(message, &signature); //! assert!(keypair.verify::<Sha512>(message, &signature).is_ok());
//!
//! assert!(verified);
//! # } //! # }
//! ``` //! ```
//! //!
@ -105,9 +103,7 @@
//! # let signature: Signature = keypair.sign::<Sha512>(message); //! # let signature: Signature = keypair.sign::<Sha512>(message);
//! //!
//! let public_key: PublicKey = keypair.public; //! let public_key: PublicKey = keypair.public;
//! let verified: bool = public_key.verify::<Sha512>(message, &signature); //! assert!(public_key.verify::<Sha512>(message, &signature).is_ok());
//!
//! assert!(verified);
//! # } //! # }
//! ``` //! ```
//! //!
@ -133,7 +129,6 @@
//! # 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();
//! # let signature: Signature = keypair.sign::<Sha512>(message); //! # let signature: Signature = keypair.sign::<Sha512>(message);
//! # let public_key: PublicKey = keypair.public; //! # let public_key: PublicKey = keypair.public;
//! # let verified: bool = public_key.verify::<Sha512>(message, &signature);
//! //!
//! let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = public_key.to_bytes(); //! let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = public_key.to_bytes();
//! let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = keypair.secret.to_bytes(); //! let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = keypair.secret.to_bytes();
@ -150,9 +145,9 @@
//! # extern crate ed25519_dalek; //! # extern crate ed25519_dalek;
//! # use rand::{Rng, ChaChaRng, SeedableRng}; //! # use rand::{Rng, ChaChaRng, SeedableRng};
//! # use sha2::Sha512; //! # use sha2::Sha512;
//! # use ed25519_dalek::{Keypair, Signature, PublicKey, SecretKey, DecodingError}; //! # use ed25519_dalek::{Keypair, Signature, PublicKey, SecretKey, SignatureError};
//! # 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), DecodingError> { //! # fn do_test() -> Result<(SecretKey, PublicKey, Keypair, Signature), SignatureError> {
//! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]); //! # let mut csprng: ChaChaRng = ChaChaRng::from_seed([0u8; 32]);
//! # let keypair_orig: Keypair = Keypair::generate::<Sha512, _>(&mut csprng); //! # let keypair_orig: Keypair = Keypair::generate::<Sha512, _>(&mut csprng);
//! # 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();
@ -267,7 +262,6 @@
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 failure; extern crate failure;
extern crate rand; extern crate rand;