Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

swap ed25519-dalek for ed25519-zebra #11781

Merged
merged 13 commits into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ crc32fast = { opt-level = 3 }
crossbeam-deque = { opt-level = 3 }
crypto-mac = { opt-level = 3 }
curve25519-dalek = { opt-level = 3 }
ed25519-dalek = { opt-level = 3 }
ed25519-zebra = { opt-level = 3 }
flate2 = { opt-level = 3 }
futures-channel = { opt-level = 3 }
hashbrown = { opt-level = 3 }
Expand Down
6 changes: 3 additions & 3 deletions primitives/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ thiserror = { version = "1.0.30", optional = true }
bitflags = "1.3"

# 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}
jakehemmerle marked this conversation as resolved.
Show resolved Hide resolved
blake2-rfc = { version = "0.2.18", default-features = false, optional = true }
schnorrkel = { version = "0.9.1", features = [
"preaudit_deprecated",
Expand Down Expand Up @@ -97,7 +97,7 @@ std = [
"sp-std/std",
"serde",
"blake2-rfc/std",
"ed25519-dalek/std",
"ed25519-zebra",
"hex/std",
"base58",
"substrate-bip39",
Expand Down Expand Up @@ -127,7 +127,7 @@ std = [
# or Intel SGX.
# For the regular wasm runtime builds this should not be used.
full_crypto = [
"ed25519-dalek",
"ed25519-zebra",
"blake2-rfc",
"schnorrkel",
"hex",
Expand Down
52 changes: 23 additions & 29 deletions primitives/core/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ use crate::crypto::{DeriveJunction, Pair as TraitPair, SecretStringError};
#[cfg(feature = "std")]
use bip39::{Language, Mnemonic, MnemonicType};
#[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")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use sp_runtime_interface::pass_by::PassByInner;
Expand Down Expand Up @@ -75,17 +77,10 @@ pub struct Public(pub [u8; 32]);

/// A key pair.
#[cfg(feature = "full_crypto")]
pub struct Pair(ed25519_dalek::Keypair);

#[cfg(feature = "full_crypto")]
impl Clone for Pair {
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"),
})
}
#[derive(Copy, Clone)]
pub struct Pair {
public: VerificationKey,
secret: SigningKey,
}

impl AsRef<[u8; 32]> for Public {
Expand Down Expand Up @@ -456,10 +451,11 @@ impl TraitPair for Pair {
///
/// You should never need to use this; generate(), generate_with_phrase
fn from_seed_slice(seed_slice: &[u8]) -> Result<Pair, SecretStringError> {
let secret = ed25519_dalek::SecretKey::from_bytes(seed_slice)
.map_err(|_| SecretStringError::InvalidSeedLength)?;
let public = ed25519_dalek::PublicKey::from(&secret);
Ok(Pair(ed25519_dalek::Keypair { secret, public }))
// does try_into consume the seed? can I consume seed_slice here? I think not right?
jakehemmerle marked this conversation as resolved.
Show resolved Hide resolved
let secret =
SigningKey::try_from(seed_slice).map_err(|_| SecretStringError::InvalidSeedLength)?;
let public = VerificationKey::from(&secret);
Ok(Pair { secret, public })
}

/// Derive a child key from a series of given junctions.
Expand All @@ -468,7 +464,7 @@ impl TraitPair for Pair {
path: Iter,
_seed: Option<Seed>,
) -> Result<(Pair, Option<Seed>), DeriveError> {
let mut acc = self.0.secret.to_bytes();
let mut acc: [u8; 32] = self.secret.into();
jakehemmerle marked this conversation as resolved.
Show resolved Hide resolved
for j in path {
match j {
DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath),
Expand All @@ -480,15 +476,13 @@ impl TraitPair for Pair {

/// Get the public key.
fn public(&self) -> Public {
let mut r = [0u8; 32];
let pk = self.0.public.as_bytes();
r.copy_from_slice(pk);
Public(r)
let pk: [u8; 32] = self.public.into();
Public(pk)
jakehemmerle marked this conversation as resolved.
Show resolved Hide resolved
}

/// Sign a message.
fn sign(&self, message: &[u8]) -> Signature {
let r = self.0.sign(message).to_bytes();
let r: [u8; 64] = self.secret.sign(message).into();
Signature::from_raw(r)
jakehemmerle marked this conversation as resolved.
Show resolved Hide resolved
}

Expand All @@ -502,17 +496,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<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,
Err(_) => return false,
};

let sig = match ed25519_dalek::Signature::try_from(sig) {
let sig = match ed25519_zebra::Signature::try_from(sig) {
Ok(s) => s,
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.
Expand All @@ -524,8 +518,8 @@ impl TraitPair for Pair {
#[cfg(feature = "full_crypto")]
impl Pair {
/// Get the seed for this key.
pub fn seed(&self) -> &Seed {
self.0.secret.as_bytes()
pub fn seed(&self) -> Seed {
self.secret.into()
}

/// Exactly as `from_string` except that if no matches are found then, the the first 32
Expand Down Expand Up @@ -577,12 +571,12 @@ mod test {
fn seed_and_derive_should_work() {
let seed = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60");
let pair = Pair::from_seed(&seed);
assert_eq!(pair.seed(), &seed);
assert_eq!(pair.seed(), seed);
let path = vec![DeriveJunction::Hard([0u8; 32])];
let derived = pair.derive(path.into_iter(), None).ok().unwrap().0;
assert_eq!(
derived.seed(),
&hex!("ede3354e133f9c8e337ddd6ee5415ed4b4ffe5fc7d21e933f4930a3730e5b21c")
hex!("ede3354e133f9c8e337ddd6ee5415ed4b4ffe5fc7d21e933f4930a3730e5b21c")
);
}

Expand Down
25 changes: 16 additions & 9 deletions primitives/io/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1895,15 +1895,18 @@ mod tests {
ext.register_extension(TaskExecutorExt::new(TaskExecutor::new()));
ext.execute_with(|| {
let pair = sr25519::Pair::generate_with_phrase(None).0;
let pair_unused = sr25519::Pair::generate_with_phrase(None).0;
crypto::start_batch_verify();
for it in 0..70 {
let msg = format!("Schnorrkel {}!", it);
let signature = pair.sign(msg.as_bytes());
crypto::sr25519_batch_verify(&signature, msg.as_bytes(), &pair.public());
}

// push invlaid
crypto::sr25519_batch_verify(&zero_sr_sig(), &Vec::new(), &zero_sr_pub());
// push invalid
let msg = b"asdf!";
let signature = pair.sign(msg);
crypto::sr25519_batch_verify(&signature, msg, &pair_unused.public());
assert!(!crypto::finish_batch_verify());

crypto::start_batch_verify();
Expand Down Expand Up @@ -1941,7 +1944,7 @@ mod tests {
// invalid ed25519 signature
jakehemmerle marked this conversation as resolved.
Show resolved Hide resolved
crypto::start_batch_verify();
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
crypto::start_batch_verify();
Expand All @@ -1961,12 +1964,14 @@ mod tests {
// 1 valid, 1 invalid ed25519 signature
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 signature = pair.sign(msg);
crypto::ed25519_batch_verify(&signature, msg, &pair.public());
let signature = pair1.sign(msg);

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());

Expand All @@ -1993,11 +1998,13 @@ mod tests {
// 1 valid sr25519, 1 invalid sr25519
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 signature = pair.sign(msg);
crypto::sr25519_batch_verify(&signature, msg, &pair.public());
let signature = pair1.sign(msg);

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());

assert!(!crypto::finish_batch_verify());
Expand Down