diff --git a/Cargo.lock b/Cargo.lock index 9c6ff6c548411..2988da14b9c1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4252,6 +4252,7 @@ dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "hash256-std-hasher 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4262,7 +4263,6 @@ dependencies = [ "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "schnorrkel 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4272,7 +4272,6 @@ dependencies = [ "substrate-serializer 1.0.0", "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index f7c23b5c8ba3e..abfdfb017cbaa 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -16,8 +16,7 @@ impl-serde = { version = "0.1", optional = true } wasmi = { version = "0.4.3", optional = true } hash-db = { version = "0.12", default-features = false } hash256-std-hasher = { version = "0.12", default-features = false } -ring = { version = "0.14", optional = true } -untrusted = { version = "0.6", optional = true } +ed25519-dalek = { version = "1.0.0-pre.1", optional = true } base58 = { version = "0.1", optional = true } blake2-rfc = { version = "0.2.18", optional = true } schnorrkel = { version = "0.1", optional = true } @@ -61,8 +60,7 @@ std = [ "rustc-hex/std", "twox-hash", "blake2-rfc", - "ring", - "untrusted", + "ed25519-dalek", "hex", "base58", "substrate-bip39", diff --git a/core/primitives/src/ed25519.rs b/core/primitives/src/ed25519.rs index 8bf3ae4ad0b56..135c551e454b7 100644 --- a/core/primitives/src/ed25519.rs +++ b/core/primitives/src/ed25519.rs @@ -22,17 +22,15 @@ use crate::{hash::H256, hash::H512}; use parity_codec::{Encode, Decode}; -#[cfg(feature = "std")] -use untrusted; #[cfg(feature = "std")] use blake2_rfc; #[cfg(feature = "std")] -use ring::{signature, signature::KeyPair, rand::{SecureRandom, SystemRandom}}; -#[cfg(feature = "std")] use substrate_bip39::seed_from_entropy; #[cfg(feature = "std")] use bip39::{Mnemonic, Language, MnemonicType}; #[cfg(feature = "std")] +use rand::Rng; +#[cfg(feature = "std")] use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError, Derive, Ss58Codec}; #[cfg(feature = "std")] use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; @@ -50,12 +48,16 @@ pub struct Public(pub [u8; 32]); /// A key pair. #[cfg(feature = "std")] -pub struct Pair(signature::Ed25519KeyPair, Seed); +pub struct Pair(ed25519_dalek::Keypair); #[cfg(feature = "std")] impl Clone for Pair { fn clone(&self) -> Self { - Pair::from_seed(self.1.clone()) + Pair(ed25519_dalek::Keypair { + public: self.0.public.clone(), + secret: ed25519_dalek::SecretKey::from_bytes(self.0.secret.as_bytes()) + .expect("key is always the correct size; qed") + }) } } @@ -359,7 +361,7 @@ impl TraitPair for Pair { /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. fn generate() -> Pair { let mut seed: Seed = Default::default(); - SystemRandom::new().fill(seed.as_mut()).expect("system random source should always work! qed"); + rand::rngs::EntropyRng::new().fill(seed.as_mut()); Self::from_seed(seed) } @@ -389,9 +391,10 @@ impl TraitPair for Pair { /// /// You should never need to use this; generate(), generate_with_phrasee fn from_seed(seed: Seed) -> Pair { - let key = signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])) + let secret = ed25519_dalek::SecretKey::from_bytes(&seed[..]) .expect("seed has valid length; qed"); - Pair(key, seed) + let public = ed25519_dalek::PublicKey::from(&secret); + Pair(ed25519_dalek::Keypair { secret, public }) } /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it @@ -410,7 +413,7 @@ impl TraitPair for Pair { /// Derive a child key from a series of given junctions. fn derive>(&self, path: Iter) -> Result { - let mut acc = self.1.clone(); + let mut acc = self.0.public.to_bytes(); for j in path { match j { DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), @@ -428,28 +431,20 @@ impl TraitPair for Pair { /// Get the public key. fn public(&self) -> Public { let mut r = [0u8; 32]; - let pk = self.0.public_key().as_ref(); + let pk = self.0.public.as_bytes(); r.copy_from_slice(pk); Public(r) } /// Sign a message. fn sign(&self, message: &[u8]) -> Signature { - let mut r = [0u8; 64]; - r.copy_from_slice(self.0.sign(message).as_ref()); + let r = self.0.sign(message).to_bytes(); Signature::from_raw(r) } /// Verify a signature on a message. Returns true if the signature is good. fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool { - let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]); - let msg = untrusted::Input::from(message.as_ref()); - let sig = untrusted::Input::from(&sig.0[..]); - - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, - } + Self::verify_weak(&sig.0[..], message.as_ref(), &pubkey.as_ref().0[..]) } /// Verify a signature on a message. Returns true if the signature is good. @@ -457,11 +452,17 @@ impl TraitPair for Pair { /// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct /// size. Use it only if you're coming from byte buffers and need the speed. fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { - let public_key = untrusted::Input::from(pubkey.as_ref()); - let msg = untrusted::Input::from(message.as_ref()); - let sig = untrusted::Input::from(sig); + let public_key = match ed25519_dalek::PublicKey::from_bytes(pubkey.as_ref()) { + Ok(pk) => pk, + Err(_) => return false, + }; + + let sig = match ed25519_dalek::Signature::from_bytes(sig) { + Ok(s) => s, + Err(_) => return false + }; - match signature::verify(&signature::ED25519, public_key, msg, sig) { + match public_key.verify(message.as_ref(), &sig) { Ok(_) => true, _ => false, } @@ -472,7 +473,7 @@ impl TraitPair for Pair { impl Pair { /// Get the seed for this key. pub fn seed(&self) -> &Seed { - &self.1 + self.0.public.as_bytes() } /// Exactly as `from_string` except that if no matches are found then, the the first 32 @@ -530,6 +531,7 @@ mod test { let message = b"Something important"; let signature = pair.sign(&message[..]); assert!(Pair::verify(&signature, &message[..], &public)); + assert!(!Pair::verify(&signature, b"Something else", &public)); } #[test] @@ -541,6 +543,7 @@ mod test { let signature = pair.sign(&message[..]); println!("Correct signature: {:?}", signature); assert!(Pair::verify(&signature, &message[..], &public)); + assert!(!Pair::verify(&signature, "Other message", &public)); } #[test]