swap ed25519-dalek for ed25519-zebra (#11781)

* swap ed25519-dalek for ed25519-zebra; no batch verificaiton

fixed batch verificaiton tests

removed additional zero verificaiton tests

removed comments, fixed test bug, added #[derive(Clone)]

Update primitives/core/src/ed25519.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* modified assertion to allow default ed25519-zebra zero key behavior

* cargo clippy

* Update primitives/core/Cargo.toml

Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>

* Update primitives/core/src/ed25519.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Update primitives/core/src/ed25519.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Update primitives/core/src/ed25519.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Update primitives/core/src/ed25519.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* updated Cargo.lock for sp-core

* fix inaccurate comment

Co-authored-by: Squirrel <gilescope@gmail.com>
Co-authored-by: Bastian Köcher <info@kchr.de>
Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
Co-authored-by: Davide Galassi <davxy@datawok.net>
This commit is contained in:
Jake Hemmerle
2022-08-15 03:53:39 -04:00
committed by GitHub
parent 2d988e5f60
commit d987d2b413
5 changed files with 57 additions and 45 deletions
+15 -1
View File
@@ -1788,6 +1788,20 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "ed25519-zebra"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403ef3e961ab98f0ba902771d29f842058578bb1ce7e3c59dad5a6a93e784c69"
dependencies = [
"curve25519-dalek 3.0.2",
"hex",
"rand_core 0.6.2",
"sha2 0.9.8",
"thiserror",
"zeroize",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.6.1" version = "1.6.1"
@@ -9624,7 +9638,7 @@ dependencies = [
"byteorder", "byteorder",
"criterion", "criterion",
"dyn-clonable", "dyn-clonable",
"ed25519-dalek", "ed25519-zebra",
"futures", "futures",
"hash-db", "hash-db",
"hash256-std-hasher", "hash256-std-hasher",
+1 -1
View File
@@ -258,7 +258,7 @@ crc32fast = { opt-level = 3 }
crossbeam-deque = { opt-level = 3 } crossbeam-deque = { opt-level = 3 }
crypto-mac = { opt-level = 3 } crypto-mac = { opt-level = 3 }
curve25519-dalek = { opt-level = 3 } curve25519-dalek = { opt-level = 3 }
ed25519-dalek = { opt-level = 3 } ed25519-zebra = { opt-level = 3 }
flate2 = { opt-level = 3 } flate2 = { opt-level = 3 }
futures-channel = { opt-level = 3 } futures-channel = { opt-level = 3 }
hashbrown = { opt-level = 3 } hashbrown = { opt-level = 3 }
+3 -3
View File
@@ -47,7 +47,7 @@ thiserror = { version = "1.0.30", optional = true }
bitflags = "1.3" bitflags = "1.3"
# full crypto # full crypto
ed25519-dalek = { version = "1.0.1", default-features = false, features = ["u64_backend", "alloc"], optional = true } ed25519-zebra = { version = "3.0.0", default-features = false, optional = true}
blake2-rfc = { version = "0.2.18", default-features = false, optional = true } blake2-rfc = { version = "0.2.18", default-features = false, optional = true }
schnorrkel = { version = "0.9.1", features = [ schnorrkel = { version = "0.9.1", features = [
"preaudit_deprecated", "preaudit_deprecated",
@@ -97,7 +97,7 @@ std = [
"sp-std/std", "sp-std/std",
"serde", "serde",
"blake2-rfc/std", "blake2-rfc/std",
"ed25519-dalek/std", "ed25519-zebra",
"hex/std", "hex/std",
"base58", "base58",
"substrate-bip39", "substrate-bip39",
@@ -127,7 +127,7 @@ std = [
# or Intel SGX. # or Intel SGX.
# For the regular wasm runtime builds this should not be used. # For the regular wasm runtime builds this should not be used.
full_crypto = [ full_crypto = [
"ed25519-dalek", "ed25519-zebra",
"blake2-rfc", "blake2-rfc",
"schnorrkel", "schnorrkel",
"hex", "hex",
+21 -30
View File
@@ -39,7 +39,9 @@ use crate::crypto::{DeriveJunction, Pair as TraitPair, SecretStringError};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use bip39::{Language, Mnemonic, MnemonicType}; use bip39::{Language, Mnemonic, MnemonicType};
#[cfg(feature = "full_crypto")] #[cfg(feature = "full_crypto")]
use ed25519_dalek::{Signer as _, Verifier as _}; use core::convert::TryFrom;
#[cfg(feature = "full_crypto")]
use ed25519_zebra::{SigningKey, VerificationKey};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use sp_runtime_interface::pass_by::PassByInner; use sp_runtime_interface::pass_by::PassByInner;
@@ -75,17 +77,10 @@ pub struct Public(pub [u8; 32]);
/// A key pair. /// A key pair.
#[cfg(feature = "full_crypto")] #[cfg(feature = "full_crypto")]
pub struct Pair(ed25519_dalek::Keypair); #[derive(Copy, Clone)]
pub struct Pair {
#[cfg(feature = "full_crypto")] public: VerificationKey,
impl Clone for Pair { secret: SigningKey,
fn clone(&self) -> Self {
Pair(ed25519_dalek::Keypair {
public: self.0.public,
secret: ed25519_dalek::SecretKey::from_bytes(self.0.secret.as_bytes())
.expect("key is always the correct size; qed"),
})
}
} }
impl AsRef<[u8; 32]> for Public { impl AsRef<[u8; 32]> for Public {
@@ -456,10 +451,10 @@ impl TraitPair for Pair {
/// ///
/// You should never need to use this; generate(), generate_with_phrase /// You should never need to use this; generate(), generate_with_phrase
fn from_seed_slice(seed_slice: &[u8]) -> Result<Pair, SecretStringError> { fn from_seed_slice(seed_slice: &[u8]) -> Result<Pair, SecretStringError> {
let secret = ed25519_dalek::SecretKey::from_bytes(seed_slice) let secret =
.map_err(|_| SecretStringError::InvalidSeedLength)?; SigningKey::try_from(seed_slice).map_err(|_| SecretStringError::InvalidSeedLength)?;
let public = ed25519_dalek::PublicKey::from(&secret); let public = VerificationKey::from(&secret);
Ok(Pair(ed25519_dalek::Keypair { secret, public })) Ok(Pair { secret, public })
} }
/// Derive a child key from a series of given junctions. /// Derive a child key from a series of given junctions.
@@ -468,7 +463,7 @@ impl TraitPair for Pair {
path: Iter, path: Iter,
_seed: Option<Seed>, _seed: Option<Seed>,
) -> Result<(Pair, Option<Seed>), DeriveError> { ) -> Result<(Pair, Option<Seed>), DeriveError> {
let mut acc = self.0.secret.to_bytes(); let mut acc = self.secret.into();
for j in path { for j in path {
match j { match j {
DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath),
@@ -480,16 +475,12 @@ impl TraitPair for Pair {
/// Get the public key. /// Get the public key.
fn public(&self) -> Public { fn public(&self) -> Public {
let mut r = [0u8; 32]; Public(self.public.into())
let pk = self.0.public.as_bytes();
r.copy_from_slice(pk);
Public(r)
} }
/// Sign a message. /// Sign a message.
fn sign(&self, message: &[u8]) -> Signature { fn sign(&self, message: &[u8]) -> Signature {
let r = self.0.sign(message).to_bytes(); Signature::from_raw(self.secret.sign(message).into())
Signature::from_raw(r)
} }
/// Verify a signature on a message. Returns true if the signature is good. /// Verify a signature on a message. Returns true if the signature is good.
@@ -502,17 +493,17 @@ impl TraitPair for Pair {
/// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct /// 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. /// size. Use it only if you're coming from byte buffers and need the speed.
fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool {
let public_key = match ed25519_dalek::PublicKey::from_bytes(pubkey.as_ref()) { let public_key = match VerificationKey::try_from(pubkey.as_ref()) {
Ok(pk) => pk, Ok(pk) => pk,
Err(_) => return false, Err(_) => return false,
}; };
let sig = match ed25519_dalek::Signature::try_from(sig) { let sig = match ed25519_zebra::Signature::try_from(sig) {
Ok(s) => s, Ok(s) => s,
Err(_) => return false, Err(_) => return false,
}; };
public_key.verify(message.as_ref(), &sig).is_ok() public_key.verify(&sig, message.as_ref()).is_ok()
} }
/// Return a vec filled with raw data. /// Return a vec filled with raw data.
@@ -524,8 +515,8 @@ impl TraitPair for Pair {
#[cfg(feature = "full_crypto")] #[cfg(feature = "full_crypto")]
impl Pair { impl Pair {
/// Get the seed for this key. /// Get the seed for this key.
pub fn seed(&self) -> &Seed { pub fn seed(&self) -> Seed {
self.0.secret.as_bytes() self.secret.into()
} }
/// Exactly as `from_string` except that if no matches are found then, the the first 32 /// Exactly as `from_string` except that if no matches are found then, the the first 32
@@ -577,12 +568,12 @@ mod test {
fn seed_and_derive_should_work() { fn seed_and_derive_should_work() {
let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60");
let pair = Pair::from_seed(&seed); let pair = Pair::from_seed(&seed);
assert_eq!(pair.seed(), &seed); assert_eq!(pair.seed(), seed);
let path = vec![DeriveJunction::Hard([0u8; 32])]; let path = vec![DeriveJunction::Hard([0u8; 32])];
let derived = pair.derive(path.into_iter(), None).ok().unwrap().0; let derived = pair.derive(path.into_iter(), None).ok().unwrap().0;
assert_eq!( assert_eq!(
derived.seed(), derived.seed(),
&hex!("ede3354e133f9c8e337ddd6ee5415ed4b4ffe5fc7d21e933f4930a3730e5b21c") hex!("ede3354e133f9c8e337ddd6ee5415ed4b4ffe5fc7d21e933f4930a3730e5b21c")
); );
} }
+17 -10
View File
@@ -1895,6 +1895,7 @@ mod tests {
ext.register_extension(TaskExecutorExt::new(TaskExecutor::new())); ext.register_extension(TaskExecutorExt::new(TaskExecutor::new()));
ext.execute_with(|| { ext.execute_with(|| {
let pair = sr25519::Pair::generate_with_phrase(None).0; let pair = sr25519::Pair::generate_with_phrase(None).0;
let pair_unused = sr25519::Pair::generate_with_phrase(None).0;
crypto::start_batch_verify(); crypto::start_batch_verify();
for it in 0..70 { for it in 0..70 {
let msg = format!("Schnorrkel {}!", it); let msg = format!("Schnorrkel {}!", it);
@@ -1902,8 +1903,10 @@ mod tests {
crypto::sr25519_batch_verify(&signature, msg.as_bytes(), &pair.public()); crypto::sr25519_batch_verify(&signature, msg.as_bytes(), &pair.public());
} }
// push invlaid // push invalid
crypto::sr25519_batch_verify(&zero_sr_sig(), &Vec::new(), &zero_sr_pub()); let msg = b"asdf!";
let signature = pair.sign(msg);
crypto::sr25519_batch_verify(&signature, msg, &pair_unused.public());
assert!(!crypto::finish_batch_verify()); assert!(!crypto::finish_batch_verify());
crypto::start_batch_verify(); crypto::start_batch_verify();
@@ -1938,10 +1941,10 @@ mod tests {
ext.register_extension(TaskExecutorExt::new(TaskExecutor::new())); ext.register_extension(TaskExecutorExt::new(TaskExecutor::new()));
ext.execute_with(|| { ext.execute_with(|| {
// invalid ed25519 signature // valid ed25519 signature
crypto::start_batch_verify(); crypto::start_batch_verify();
crypto::ed25519_batch_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()); crypto::ed25519_batch_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub());
assert!(!crypto::finish_batch_verify()); assert!(crypto::finish_batch_verify());
// 2 valid ed25519 signatures // 2 valid ed25519 signatures
crypto::start_batch_verify(); crypto::start_batch_verify();
@@ -1961,12 +1964,14 @@ mod tests {
// 1 valid, 1 invalid ed25519 signature // 1 valid, 1 invalid ed25519 signature
crypto::start_batch_verify(); crypto::start_batch_verify();
let pair = ed25519::Pair::generate_with_phrase(None).0; let pair1 = ed25519::Pair::generate_with_phrase(None).0;
let pair2 = ed25519::Pair::generate_with_phrase(None).0;
let msg = b"Important message"; let msg = b"Important message";
let signature = pair.sign(msg); let signature = pair1.sign(msg);
crypto::ed25519_batch_verify(&signature, msg, &pair.public());
crypto::ed25519_batch_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub()); crypto::ed25519_batch_verify(&zero_ed_sig(), &Vec::new(), &zero_ed_pub());
crypto::ed25519_batch_verify(&signature, msg, &pair1.public());
crypto::ed25519_batch_verify(&signature, msg, &pair2.public());
assert!(!crypto::finish_batch_verify()); assert!(!crypto::finish_batch_verify());
@@ -1993,11 +1998,13 @@ mod tests {
// 1 valid sr25519, 1 invalid sr25519 // 1 valid sr25519, 1 invalid sr25519
crypto::start_batch_verify(); crypto::start_batch_verify();
let pair = sr25519::Pair::generate_with_phrase(None).0; let pair1 = sr25519::Pair::generate_with_phrase(None).0;
let pair2 = sr25519::Pair::generate_with_phrase(None).0;
let msg = b"Schnorrkcel!"; let msg = b"Schnorrkcel!";
let signature = pair.sign(msg); let signature = pair1.sign(msg);
crypto::sr25519_batch_verify(&signature, msg, &pair.public());
crypto::sr25519_batch_verify(&signature, msg, &pair1.public());
crypto::sr25519_batch_verify(&signature, msg, &pair2.public());
crypto::sr25519_batch_verify(&zero_sr_sig(), &Vec::new(), &zero_sr_pub()); crypto::sr25519_batch_verify(&zero_sr_sig(), &Vec::new(), &zero_sr_pub());
assert!(!crypto::finish_batch_verify()); assert!(!crypto::finish_batch_verify());