Skip to content

Commit dd35dcb

Browse files
committed
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 paritytech#9356
1 parent 4d93a6e commit dd35dcb

File tree

3 files changed

+93
-54
lines changed

3 files changed

+93
-54
lines changed

Cargo.lock

+64-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

primitives/core/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ schnorrkel = { version = "0.9.1", features = ["preaudit_deprecated", "u64_backen
4949
sha2 = { version = "0.9.2", default-features = false, optional = true }
5050
hex = { version = "0.4", default-features = false, optional = true }
5151
twox-hash = { version = "1.5.0", default-features = false, optional = true }
52-
libsecp256k1 = { version = "0.3.2", default-features = false, features = ["hmac"], optional = true }
52+
libsecp256k1 = { version = "0.6", default-features = false, features = ["hmac", "static-context"], optional = true }
5353
merlin = { version = "2.0", default-features = false, optional = true }
5454

5555
sp-runtime-interface = { version = "4.0.0-dev", default-features = false, path = "../runtime-interface" }

primitives/core/src/ecdsa.rs

+28-48
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,7 @@ use bip39::{Language, Mnemonic, MnemonicType};
4040
#[cfg(feature = "full_crypto")]
4141
use core::convert::{TryFrom, TryInto};
4242
#[cfg(feature = "full_crypto")]
43-
use secp256k1::{PublicKey, SecretKey};
44-
#[cfg(feature = "std")]
45-
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
46-
use sp_runtime_interface::pass_by::PassByInner;
47-
#[cfg(feature = "std")]
48-
use substrate_bip39::seed_from_entropy;
43+
use libsecp256k1::{PublicKey, SecretKey};
4944

5045
/// An identifier used to match public keys against ecdsa keys
5146
pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds");
@@ -108,7 +103,7 @@ impl Public {
108103
/// This will convert the full public key into the compressed format.
109104
#[cfg(feature = "std")]
110105
pub fn from_full(full: &[u8]) -> Result<Self, ()> {
111-
secp256k1::PublicKey::parse_slice(full, None)
106+
libsecp256k1::PublicKey::parse_slice(full, None)
112107
.map(|k| k.serialize_compressed())
113108
.map(Self)
114109
.map_err(|_| ())
@@ -364,29 +359,29 @@ impl Signature {
364359
/// Recover the public key from this signature and a message.
365360
#[cfg(feature = "full_crypto")]
366361
pub fn recover<M: AsRef<[u8]>>(&self, message: M) -> Option<Public> {
367-
let message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
362+
let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref()));
368363
let sig: (_, _) = self.try_into().ok()?;
369-
secp256k1::recover(&message, &sig.0, &sig.1)
364+
libsecp256k1::recover(&message, &sig.0, &sig.1)
370365
.ok()
371366
.map(|recovered| Public(recovered.serialize_compressed()))
372367
}
373368

374369
/// Recover the public key from this signature and a pre-hashed message.
375370
#[cfg(feature = "full_crypto")]
376371
pub fn recover_prehashed(&self, message: &[u8; 32]) -> Option<Public> {
377-
let message = secp256k1::Message::parse(message);
372+
let message = libsecp256k1::Message::parse(message);
378373

379374
let sig: (_, _) = self.try_into().ok()?;
380375

381-
secp256k1::recover(&message, &sig.0, &sig.1)
376+
libsecp256k1::recover(&message, &sig.0, &sig.1)
382377
.ok()
383378
.map(|key| Public(key.serialize_compressed()))
384379
}
385380
}
386381

387382
#[cfg(feature = "full_crypto")]
388-
impl From<(secp256k1::Signature, secp256k1::RecoveryId)> for Signature {
389-
fn from(x: (secp256k1::Signature, secp256k1::RecoveryId)) -> Signature {
383+
impl From<(libsecp256k1::Signature, libsecp256k1::RecoveryId)> for Signature {
384+
fn from(x: (libsecp256k1::Signature, libsecp256k1::RecoveryId)) -> Signature {
390385
let mut r = Self::default();
391386
r.0[0..64].copy_from_slice(&x.0.serialize()[..]);
392387
r.0[64] = x.1.serialize();
@@ -395,14 +390,12 @@ impl From<(secp256k1::Signature, secp256k1::RecoveryId)> for Signature {
395390
}
396391

397392
#[cfg(feature = "full_crypto")]
398-
impl<'a> TryFrom<&'a Signature> for (secp256k1::Signature, secp256k1::RecoveryId) {
393+
impl<'a> TryFrom<&'a Signature> for (libsecp256k1::Signature, libsecp256k1::RecoveryId) {
399394
type Error = ();
400-
fn try_from(
401-
x: &'a Signature,
402-
) -> Result<(secp256k1::Signature, secp256k1::RecoveryId), Self::Error> {
395+
fn try_from(x: &'a Signature) -> Result<(libsecp256k1::Signature, libsecp256k1::RecoveryId), Self::Error> {
403396
Ok((
404-
secp256k1::Signature::parse_slice(&x.0[0..64]).expect("hardcoded to 64 bytes; qed"),
405-
secp256k1::RecoveryId::parse(x.0[64]).map_err(|_| ())?,
397+
libsecp256k1::Signature::parse_standard_slice(&x.0[0..64]).expect("hardcoded to 64 bytes; qed"),
398+
libsecp256k1::RecoveryId::parse(x.0[64]).map_err(|_| ())?,
406399
))
407400
}
408401
}
@@ -510,18 +503,15 @@ impl TraitPair for Pair {
510503

511504
/// Sign a message.
512505
fn sign(&self, message: &[u8]) -> Signature {
513-
let message = secp256k1::Message::parse(&blake2_256(message));
514-
secp256k1::sign(&message, &self.secret).into()
506+
let message = libsecp256k1::Message::parse(&blake2_256(message));
507+
libsecp256k1::sign(&message, &self.secret).into()
515508
}
516509

517510
/// Verify a signature on a message. Returns true if the signature is good.
518511
fn verify<M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: &Self::Public) -> bool {
519-
let message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
520-
let sig: (_, _) = match sig.try_into() {
521-
Ok(x) => x,
522-
_ => return false,
523-
};
524-
match secp256k1::recover(&message, &sig.0, &sig.1) {
512+
let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref()));
513+
let sig: (_, _) = match sig.try_into() { Ok(x) => x, _ => return false };
514+
match libsecp256k1::recover(&message, &sig.0, &sig.1) {
525515
Ok(actual) => pubkey.0[..] == actual.serialize_compressed()[..],
526516
_ => false,
527517
}
@@ -532,19 +522,11 @@ impl TraitPair for Pair {
532522
/// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct
533523
/// size. Use it only if you're coming from byte buffers and need the speed.
534524
fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool {
535-
let message = secp256k1::Message::parse(&blake2_256(message.as_ref()));
536-
if sig.len() != 65 {
537-
return false
538-
}
539-
let ri = match secp256k1::RecoveryId::parse(sig[64]) {
540-
Ok(x) => x,
541-
_ => return false,
542-
};
543-
let sig = match secp256k1::Signature::parse_slice(&sig[0..64]) {
544-
Ok(x) => x,
545-
_ => return false,
546-
};
547-
match secp256k1::recover(&message, &sig, &ri) {
525+
let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref()));
526+
if sig.len() != 65 { return false }
527+
let ri = match libsecp256k1::RecoveryId::parse(sig[64]) { Ok(x) => x, _ => return false };
528+
let sig = match libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) { Ok(x) => x, _ => return false };
529+
match libsecp256k1::recover(&message, &sig, &ri) {
548530
Ok(actual) => pubkey.as_ref() == &actual.serialize()[1..],
549531
_ => false,
550532
}
@@ -577,21 +559,21 @@ impl Pair {
577559

578560
/// Sign a pre-hashed message
579561
pub fn sign_prehashed(&self, message: &[u8; 32]) -> Signature {
580-
let message = secp256k1::Message::parse(message);
581-
secp256k1::sign(&message, &self.secret).into()
562+
let message = libsecp256k1::Message::parse(message);
563+
libsecp256k1::sign(&message, &self.secret).into()
582564
}
583565

584566
/// Verify a signature on a pre-hashed message. Return `true` if the signature is valid
585567
/// and thus matches the given `public` key.
586568
pub fn verify_prehashed(sig: &Signature, message: &[u8; 32], public: &Public) -> bool {
587-
let message = secp256k1::Message::parse(message);
569+
let message = libsecp256k1::Message::parse(message);
588570

589571
let sig: (_, _) = match sig.try_into() {
590572
Ok(x) => x,
591573
_ => return false,
592574
};
593575

594-
match secp256k1::recover(&message, &sig.0, &sig.1) {
576+
match libsecp256k1::recover(&message, &sig.0, &sig.1) {
595577
Ok(actual) => public.0[..] == actual.serialize_compressed()[..],
596578
_ => false,
597579
}
@@ -839,8 +821,7 @@ mod test {
839821
// `msg` shouldn't be mangled
840822
let msg = [0u8; 32];
841823
let sig1 = pair.sign_prehashed(&msg);
842-
let sig2: Signature =
843-
secp256k1::sign(&secp256k1::Message::parse(&msg), &pair.secret).into();
824+
let sig2: Signature = libsecp256k1::sign(&libsecp256k1::Message::parse(&msg), &pair.secret).into();
844825

845826
assert_eq!(sig1, sig2);
846827

@@ -852,8 +833,7 @@ mod test {
852833
// using pre-hashed `msg` works
853834
let msg = keccak_256(b"this should be hashed");
854835
let sig1 = pair.sign_prehashed(&msg);
855-
let sig2: Signature =
856-
secp256k1::sign(&secp256k1::Message::parse(&msg), &pair.secret).into();
836+
let sig2: Signature = libsecp256k1::sign(&libsecp256k1::Message::parse(&msg), &pair.secret).into();
857837

858838
assert_eq!(sig1, sig2);
859839
}

0 commit comments

Comments
 (0)