diff --git a/Cargo.toml b/Cargo.toml index ef37fd1..c094c89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,14 +11,14 @@ authors = [ exclude = [".gitignore", ".github/"] [dependencies] -curve25519-dalek = "3" +curve25519-dalek = { version = "4.1", features = ["legacy_compatibility", "digest"]} rand = "0.8" -sha2 = "0.9" +sha2 = "0.10" serde = { version = "1.0", optional = true } zeroize = "1.5.7" [dev-dependencies] -ed25519-dalek = "1.0.1" +ed25519-dalek = { version = "2.1", features = ["hazmat"] } rand_xoshiro = "0.6.0" hex = "0.4.3" serde_test = "1" diff --git a/src/aggregate.rs b/src/aggregate.rs index a0e8f68..dd058b9 100644 --- a/src/aggregate.rs +++ b/src/aggregate.rs @@ -45,20 +45,21 @@ impl AggPublicKeyAndMusigCoeff { edwards_from_bytes(&keys[1]).ok_or(Error::InvalidPublicKey)?, ]; - let first_musig_coefficient = Scalar::from_hash( - Sha512::new() - .chain("musig2 public key aggregation") - .chain(keys[0]) - .chain(keys[1]) - .chain(keys[0]), - ); + let mut hasher = Sha512::new(); + Digest::update(&mut hasher, "musig2 public key aggregation"); + Digest::update(&mut hasher, keys[0]); + Digest::update(&mut hasher, keys[1]); + Digest::update(&mut hasher, keys[0]); + + + let first_musig_coefficient = Scalar::from_hash(hasher); let agg_public_key = first_musig_coefficient * edwards_keys[0] + edwards_keys[1]; let musig_coefficient = if location == KeySortedLocation::First { first_musig_coefficient } else { - Scalar::one() + Scalar::ONE }; Ok(Self { diff --git a/src/common.rs b/src/common.rs index c8d4f9f..ffc45c1 100644 --- a/src/common.rs +++ b/src/common.rs @@ -11,7 +11,7 @@ use std::convert::TryInto; /// If the input `bytes` slice does not have a length of 32. #[inline(always)] pub fn edwards_from_bytes(bytes: &[u8]) -> Option { - let point = CompressedEdwardsY::from_slice(bytes).decompress()?; + let point = CompressedEdwardsY::from_slice(bytes).ok()?.decompress()?; // We require that the point will be 0 in the small subgroup, // `is_small_order()` checks if the point is *only* in the small subgroup, // while `is_torsion_free()` makes sure the point is 0 in the small subgroup. @@ -37,7 +37,7 @@ pub fn scalar_from_bytes(bytes: &[u8]) -> Option { if bytes[31] & 240 == 0 { Some(Scalar::from_bits(bytes)) } else { - Scalar::from_canonical_bytes(bytes) + Scalar::from_canonical_bytes(bytes).into() } } diff --git a/src/derive.rs b/src/derive.rs index bce191c..03a3a59 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -95,11 +95,11 @@ pub fn derive_delta_and_public_key_from_path( path: &[u32], ) -> (Scalar, EdwardsPoint) { path.iter() - .fold((Scalar::zero(), pk), |(delta_sum, pk_derived), &i| { + .fold((Scalar::ZERO, pk), |(delta_sum, pk_derived), &i| { let delta = compute_delta(&pk_derived, i); ( delta_sum + delta, - pk_derived + &delta * &ED25519_BASEPOINT_TABLE, + pk_derived + &delta * ED25519_BASEPOINT_TABLE, ) }) } @@ -122,10 +122,10 @@ mod tests { fn test_public_and_delta_sanity_empty_path() { let mut rng = Xoshiro256PlusPlus::seed_from_u64(0); let sk = sample_scalar(&mut rng); - let pk = &sk * &ED25519_BASEPOINT_TABLE; + let pk = &sk * ED25519_BASEPOINT_TABLE; assert_eq!( derive_delta_and_public_key_from_path(pk, &[]).0, - Scalar::zero() + Scalar::ZERO ); assert_eq!(derive_delta_and_public_key_from_path(pk, &[]).1, pk); } @@ -134,22 +134,22 @@ mod tests { fn test_public_and_delta_sanity_path_length_one() { let mut rng = Xoshiro256PlusPlus::seed_from_u64(1); let sk = sample_scalar(&mut rng); - let pk = &sk * &ED25519_BASEPOINT_TABLE; + let pk = &sk * ED25519_BASEPOINT_TABLE; let path = [1]; let delta = derive_delta_and_public_key_from_path(pk, &path).0; let derived_pk = derive_delta_and_public_key_from_path(pk, &path).1; - assert_ne!(delta, Scalar::zero()); - assert_eq!(derived_pk, pk + &delta * &ED25519_BASEPOINT_TABLE); + assert_ne!(delta, Scalar::ZERO); + assert_eq!(derived_pk, pk + &delta * ED25519_BASEPOINT_TABLE); } #[test] fn test_public_and_delta_sanity_path_length_two() { let mut rng = Xoshiro256PlusPlus::seed_from_u64(1); let sk = sample_scalar(&mut rng); - let pk = &sk * &ED25519_BASEPOINT_TABLE; + let pk = &sk * ED25519_BASEPOINT_TABLE; let path = [1, u32::MAX]; let delta = derive_delta_and_public_key_from_path(pk, &path).0; let derived_pk = derive_delta_and_public_key_from_path(pk, &path).1; - assert_ne!(delta, Scalar::zero()); - assert_eq!(derived_pk, pk + &delta * &ED25519_BASEPOINT_TABLE); + assert_ne!(delta, Scalar::ZERO); + assert_eq!(derived_pk, pk + &delta * ED25519_BASEPOINT_TABLE); } } diff --git a/src/keypair.rs b/src/keypair.rs index 8687541..d7986d7 100644 --- a/src/keypair.rs +++ b/src/keypair.rs @@ -12,6 +12,7 @@ use curve25519_dalek::scalar::Scalar; use rand::{thread_rng, Rng}; use sha2::{Digest, Sha512}; use zeroize::Zeroize; +use curve25519_dalek::digest::Update; /// An ed25519 keypair pub struct KeyPair { @@ -43,7 +44,7 @@ impl KeyPair { private_key_bits[31] &= 63; private_key_bits[31] |= 64; let private_key = Scalar::from_bits(private_key_bits); - let public_key = &private_key * &constants::ED25519_BASEPOINT_TABLE; + let public_key = &private_key * constants::ED25519_BASEPOINT_TABLE; Self { public_key, prefix, @@ -142,7 +143,7 @@ impl KeyPair { .chain(thread_rng().gen::<[u8; 32]>()), ) }); - let R: [EdwardsPoint; 2] = r.map(|scalar| &scalar * &constants::ED25519_BASEPOINT_TABLE); + let R: [EdwardsPoint; 2] = r.map(|scalar| &scalar * constants::ED25519_BASEPOINT_TABLE); (PrivatePartialNonces(r), PublicPartialNonces(R)) } } diff --git a/src/lib.rs b/src/lib.rs index 27bbabc..b4f87e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,8 +65,8 @@ mod tests { } pub fn verify_dalek(pk: [u8; 32], sig: [u8; 64], msg: &[u8]) -> bool { - let dalek_pub = ed25519_dalek::PublicKey::from_bytes(&pk).unwrap(); - let dalek_sig = ed25519_dalek::Signature::from_bytes(&sig).unwrap(); + let dalek_pub = ed25519_dalek::VerifyingKey::from_bytes(&pk).unwrap(); + let dalek_sig = ed25519_dalek::Signature::from_bytes(&sig); dalek_pub.verify(msg, &dalek_sig).is_ok() } @@ -79,10 +79,9 @@ mod tests { for _ in 0..4096 { rng.fill_bytes(&mut privkey); let zengo_keypair = KeyPair::create_from_private_key(privkey); - let dalek_secret = ed25519_dalek::SecretKey::from_bytes(&privkey) + let dalek_secret = ed25519_dalek::SecretKey::try_from(privkey) .expect("Can only fail if bytes.len()<32"); - let dalek_pub = ed25519_dalek::PublicKey::from(&dalek_secret); - + let dalek_pub = ed25519_dalek::VerifyingKey::from_bytes(&privkey).unwrap(); assert_eq!(zengo_keypair.pubkey(), dalek_pub.to_bytes()); } } @@ -97,11 +96,11 @@ mod tests { let msg = &mut msg[..msg_len]; rng.fill_bytes(&mut privkey); rng.fill_bytes(msg); - let dalek_secret = ed25519_dalek::SecretKey::from_bytes(&privkey) - .expect("Can only fail if bytes.len()<32"); - let dalek_expanded_secret = ed25519_dalek::ExpandedSecretKey::from(&dalek_secret); - let dalek_pub = ed25519_dalek::PublicKey::from(&dalek_expanded_secret); - let dalek_sig = dalek_expanded_secret.sign(msg, &dalek_pub); + // let dalek_secret = ed25519_dalek::SecretKey::from_bytes(&privkey) + // .expect("Can only fail if bytes.len()<32"); + let dalek_expanded_secret = ed25519_dalek::hazmat::ExpandedSecretKey::from(&privkey); + let dalek_pub = ed25519_dalek::VerifyingKey::from(&dalek_expanded_secret); + let dalek_sig = ed25519_dalek::hazmat::raw_sign::(&dalek_expanded_secret, msg, &dalek_pub); let zengo_sig = Signature::deserialize(dalek_sig.to_bytes()).unwrap(); zengo_sig.verify(msg, dalek_pub.to_bytes()).unwrap(); @@ -223,8 +222,8 @@ mod tests { ); // only one of them should be equal to 1. assert_ne!( - self.aggpubkey1.musig_coefficient == Scalar::one(), - self.aggpubkey2.musig_coefficient == Scalar::one() + self.aggpubkey1.musig_coefficient == Scalar::ONE, + self.aggpubkey2.musig_coefficient == Scalar::ONE ); } diff --git a/src/signature.rs b/src/signature.rs index 2ba0427..6190ad9 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -47,7 +47,7 @@ impl Signature { let kA = A * k; let R_plus_kA = kA + self.R; - let sG = &self.s * &constants::ED25519_BASEPOINT_TABLE; + let sG = &self.s * constants::ED25519_BASEPOINT_TABLE; if R_plus_kA == sG { Ok(()) @@ -58,12 +58,12 @@ impl Signature { // This is the Fiat-Shamir hash of all protocol state before signing. pub(crate) fn k(R: &EdwardsPoint, PK: &EdwardsPoint, message: &[u8]) -> Scalar { - Scalar::from_hash( - Sha512::new() - .chain(R.compress().as_bytes()) - .chain(PK.compress().as_bytes()) - .chain(message), - ) + let mut hasher = Sha512::new(); + Digest::update(&mut hasher, R.compress().as_bytes()); + Digest::update(&mut hasher, PK.compress().as_bytes()); + Digest::update(&mut hasher, message); + + Scalar::from_hash(hasher) } /// Serialize the signature