mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-01 14:47:55 +00:00
RUSTSEC-2021-0076 bump libsecp256k1 (#9391)
* RUSTSEC-2021-0076 bump libsecp256k1 libsecp256k1 allows overflowing signatures https://rustsec.org/advisories/RUSTSEC-2021-0076 Changes were made to conform to libsecp256k1 version differences. Closes #9356 * parse_standard_slice() -> parse_overflowing_slice() * Added v2 host function for ecdsa_verify * Add feature tag over helpers * Added ecdsa_verify v2 to test runner * PR feedback - Spaces -> tabs - renamed two helper functions * Fixed imports after rebasing * Bump rest of libsecp256k1 (and libp2p) libp2p also uses libsecp256k1 so it is required to be bumped too, along with all the version difference changes. * Add version2 for ecdsa pubkey recovery * libp2p rebase master fixes * Fix test panic when non Behaviour event is returned * Update bin/node/browser-testing/Cargo.toml * Update primitives/core/src/ecdsa.rs * Update primitives/core/src/ecdsa.rs * Update Cargo.lock Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -19,10 +19,8 @@
|
||||
//! Simple ECDSA API.
|
||||
// end::description[]
|
||||
|
||||
#[cfg(feature = "full_crypto")]
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use sp_runtime_interface::pass_by::PassByInner;
|
||||
use sp_std::cmp::Ordering;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
@@ -40,12 +38,11 @@ use bip39::{Language, Mnemonic, MnemonicType};
|
||||
#[cfg(feature = "full_crypto")]
|
||||
use core::convert::{TryFrom, TryInto};
|
||||
#[cfg(feature = "full_crypto")]
|
||||
use secp256k1::{PublicKey, SecretKey};
|
||||
use libsecp256k1::{PublicKey, SecretKey};
|
||||
#[cfg(feature = "std")]
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use sp_runtime_interface::pass_by::PassByInner;
|
||||
#[cfg(feature = "std")]
|
||||
use substrate_bip39::seed_from_entropy;
|
||||
#[cfg(feature = "full_crypto")]
|
||||
use sp_std::vec::Vec;
|
||||
|
||||
/// An identifier used to match public keys against ecdsa keys
|
||||
pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds");
|
||||
@@ -108,7 +105,7 @@ impl Public {
|
||||
/// This will convert the full public key into the compressed format.
|
||||
#[cfg(feature = "std")]
|
||||
pub fn from_full(full: &[u8]) -> Result<Self, ()> {
|
||||
secp256k1::PublicKey::parse_slice(full, None)
|
||||
libsecp256k1::PublicKey::parse_slice(full, None)
|
||||
.map(|k| k.serialize_compressed())
|
||||
.map(Self)
|
||||
.map_err(|_| ())
|
||||
@@ -364,9 +361,9 @@ impl Signature {
|
||||
/// Recover the public key from this signature and a message.
|
||||
#[cfg(feature = "full_crypto")]
|
||||
pub fn recover<M: AsRef<[u8]>>(&self, message: M) -> Option<Public> {
|
||||
let message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
|
||||
let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref()));
|
||||
let sig: (_, _) = self.try_into().ok()?;
|
||||
secp256k1::recover(&message, &sig.0, &sig.1)
|
||||
libsecp256k1::recover(&message, &sig.0, &sig.1)
|
||||
.ok()
|
||||
.map(|recovered| Public(recovered.serialize_compressed()))
|
||||
}
|
||||
@@ -374,19 +371,19 @@ impl Signature {
|
||||
/// Recover the public key from this signature and a pre-hashed message.
|
||||
#[cfg(feature = "full_crypto")]
|
||||
pub fn recover_prehashed(&self, message: &[u8; 32]) -> Option<Public> {
|
||||
let message = secp256k1::Message::parse(message);
|
||||
let message = libsecp256k1::Message::parse(message);
|
||||
|
||||
let sig: (_, _) = self.try_into().ok()?;
|
||||
|
||||
secp256k1::recover(&message, &sig.0, &sig.1)
|
||||
libsecp256k1::recover(&message, &sig.0, &sig.1)
|
||||
.ok()
|
||||
.map(|key| Public(key.serialize_compressed()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "full_crypto")]
|
||||
impl From<(secp256k1::Signature, secp256k1::RecoveryId)> for Signature {
|
||||
fn from(x: (secp256k1::Signature, secp256k1::RecoveryId)) -> Signature {
|
||||
impl From<(libsecp256k1::Signature, libsecp256k1::RecoveryId)> for Signature {
|
||||
fn from(x: (libsecp256k1::Signature, libsecp256k1::RecoveryId)) -> Signature {
|
||||
let mut r = Self::default();
|
||||
r.0[0..64].copy_from_slice(&x.0.serialize()[..]);
|
||||
r.0[64] = x.1.serialize();
|
||||
@@ -395,15 +392,12 @@ impl From<(secp256k1::Signature, secp256k1::RecoveryId)> for Signature {
|
||||
}
|
||||
|
||||
#[cfg(feature = "full_crypto")]
|
||||
impl<'a> TryFrom<&'a Signature> for (secp256k1::Signature, secp256k1::RecoveryId) {
|
||||
impl<'a> TryFrom<&'a Signature> for (libsecp256k1::Signature, libsecp256k1::RecoveryId) {
|
||||
type Error = ();
|
||||
fn try_from(
|
||||
x: &'a Signature,
|
||||
) -> Result<(secp256k1::Signature, secp256k1::RecoveryId), Self::Error> {
|
||||
Ok((
|
||||
secp256k1::Signature::parse_slice(&x.0[0..64]).expect("hardcoded to 64 bytes; qed"),
|
||||
secp256k1::RecoveryId::parse(x.0[64]).map_err(|_| ())?,
|
||||
))
|
||||
) -> Result<(libsecp256k1::Signature, libsecp256k1::RecoveryId), Self::Error> {
|
||||
parse_signature_standard(&x.0).map_err(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +451,7 @@ impl TraitPair for Pair {
|
||||
phrase: &str,
|
||||
password: Option<&str>,
|
||||
) -> Result<(Pair, Seed), SecretStringError> {
|
||||
let big_seed = seed_from_entropy(
|
||||
let big_seed = substrate_bip39::seed_from_entropy(
|
||||
Mnemonic::from_phrase(phrase, Language::English)
|
||||
.map_err(|_| SecretStringError::InvalidPhrase)?
|
||||
.entropy(),
|
||||
@@ -510,18 +504,18 @@ impl TraitPair for Pair {
|
||||
|
||||
/// Sign a message.
|
||||
fn sign(&self, message: &[u8]) -> Signature {
|
||||
let message = secp256k1::Message::parse(&blake2_256(message));
|
||||
secp256k1::sign(&message, &self.secret).into()
|
||||
let message = libsecp256k1::Message::parse(&blake2_256(message));
|
||||
libsecp256k1::sign(&message, &self.secret).into()
|
||||
}
|
||||
|
||||
/// Verify a signature on a message. Returns true if the signature is good.
|
||||
fn verify<M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool {
|
||||
let message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
|
||||
let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref()));
|
||||
let sig: (_, _) = match sig.try_into() {
|
||||
Ok(x) => x,
|
||||
_ => return false,
|
||||
};
|
||||
match secp256k1::recover(&message, &sig.0, &sig.1) {
|
||||
match libsecp256k1::recover(&message, &sig.0, &sig.1) {
|
||||
Ok(actual) => pubkey.0[..] == actual.serialize_compressed()[..],
|
||||
_ => false,
|
||||
}
|
||||
@@ -532,19 +526,15 @@ 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 message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
|
||||
let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref()));
|
||||
if sig.len() != 65 {
|
||||
return false
|
||||
}
|
||||
let ri = match secp256k1::RecoveryId::parse(sig[64]) {
|
||||
Ok(x) => x,
|
||||
let (sig, ri) = match parse_signature_standard(&sig) {
|
||||
Ok(sigri) => sigri,
|
||||
_ => return false,
|
||||
};
|
||||
let sig = match secp256k1::Signature::parse_slice(&sig[0..64]) {
|
||||
Ok(x) => x,
|
||||
_ => return false,
|
||||
};
|
||||
match secp256k1::recover(&message, &sig, &ri) {
|
||||
match libsecp256k1::recover(&message, &sig, &ri) {
|
||||
Ok(actual) => pubkey.as_ref() == &actual.serialize()[1..],
|
||||
_ => false,
|
||||
}
|
||||
@@ -577,25 +567,57 @@ impl Pair {
|
||||
|
||||
/// Sign a pre-hashed message
|
||||
pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature {
|
||||
let message = secp256k1::Message::parse(message);
|
||||
secp256k1::sign(&message, &self.secret).into()
|
||||
let message = libsecp256k1::Message::parse(message);
|
||||
libsecp256k1::sign(&message, &self.secret).into()
|
||||
}
|
||||
|
||||
/// Verify a signature on a pre-hashed message. Return `true` if the signature is valid
|
||||
/// and thus matches the given `public` key.
|
||||
pub fn verify_prehashed(sig: &Signature, message: &[u8; 32], public: &Public) -> bool {
|
||||
let message = secp256k1::Message::parse(message);
|
||||
let message = libsecp256k1::Message::parse(message);
|
||||
|
||||
let sig: (_, _) = match sig.try_into() {
|
||||
Ok(x) => x,
|
||||
_ => return false,
|
||||
};
|
||||
|
||||
match secp256k1::recover(&message, &sig.0, &sig.1) {
|
||||
match libsecp256k1::recover(&message, &sig.0, &sig.1) {
|
||||
Ok(actual) => public.0[..] == actual.serialize_compressed()[..],
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify a signature on a message. Returns true if the signature is good.
|
||||
/// Parses Signature using parse_overflowing_slice
|
||||
pub fn verify_deprecated<M: AsRef<[u8]>>(sig: &Signature, message: M, pubkey: &Public) -> bool {
|
||||
let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref()));
|
||||
let (sig, ri) = match parse_signature_overflowing(&sig.0) {
|
||||
Ok(sigri) => sigri,
|
||||
_ => return false,
|
||||
};
|
||||
match libsecp256k1::recover(&message, &sig, &ri) {
|
||||
Ok(actual) => pubkey.0[..] == actual.serialize_compressed()[..],
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "full_crypto")]
|
||||
fn parse_signature_standard(
|
||||
x: &[u8],
|
||||
) -> Result<(libsecp256k1::Signature, libsecp256k1::RecoveryId), libsecp256k1::Error> {
|
||||
let sig = libsecp256k1::Signature::parse_standard_slice(&x[..64])?;
|
||||
let ri = libsecp256k1::RecoveryId::parse(x[64])?;
|
||||
Ok((sig, ri))
|
||||
}
|
||||
|
||||
#[cfg(feature = "full_crypto")]
|
||||
fn parse_signature_overflowing(
|
||||
x: &[u8],
|
||||
) -> Result<(libsecp256k1::Signature, libsecp256k1::RecoveryId), libsecp256k1::Error> {
|
||||
let sig = libsecp256k1::Signature::parse_overflowing_slice(&x[..64])?;
|
||||
let ri = libsecp256k1::RecoveryId::parse(x[64])?;
|
||||
Ok((sig, ri))
|
||||
}
|
||||
|
||||
impl CryptoType for Public {
|
||||
@@ -840,7 +862,7 @@ mod test {
|
||||
let msg = [0u8; 32];
|
||||
let sig1 = pair.sign_prehashed(&msg);
|
||||
let sig2: Signature =
|
||||
secp256k1::sign(&secp256k1::Message::parse(&msg), &pair.secret).into();
|
||||
libsecp256k1::sign(&libsecp256k1::Message::parse(&msg), &pair.secret).into();
|
||||
|
||||
assert_eq!(sig1, sig2);
|
||||
|
||||
@@ -853,7 +875,7 @@ mod test {
|
||||
let msg = keccak_256(b"this should be hashed");
|
||||
let sig1 = pair.sign_prehashed(&msg);
|
||||
let sig2: Signature =
|
||||
secp256k1::sign(&secp256k1::Message::parse(&msg), &pair.secret).into();
|
||||
libsecp256k1::sign(&libsecp256k1::Message::parse(&msg), &pair.secret).into();
|
||||
|
||||
assert_eq!(sig1, sig2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user