Skip to content

Commit

Permalink
Replace unmaintained parity-secp256k1 to secp256k1 (#7000)
Browse files Browse the repository at this point in the history
This PR replaces an unmaintained fork of secp256k1 to the latest version of the original library that already have all required features with a more clear API. Also this will solve compilation issues with llvm 13.* tools on MacOS like the next: rust-lang/rust-bindgen#1834
  • Loading branch information
ahlinc authored and nikurt committed Nov 9, 2022
1 parent 2ef58d7 commit 5a1f8c6
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 50 deletions.
33 changes: 20 additions & 13 deletions 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 core/crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ derive_more = "0.99.9"
ed25519-dalek = "1"
primitive-types = { version = "0.10", default-features = false }
once_cell = "1.5.2"
parity-secp256k1 = "0.7"
secp256k1 = { version = "0.24", features = ["recovery", "rand-std"] }
rand = "0.7"
serde = { version = "1", features = [ "derive" ] }
serde_json = "1"
Expand Down
54 changes: 25 additions & 29 deletions core/crypto/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use rand::rngs::OsRng;
use secp256k1::Message;
use serde::{Deserialize, Serialize};

pub static SECP256K1: Lazy<secp256k1::Secp256k1> = Lazy::new(secp256k1::Secp256k1::new);
pub static SECP256K1: Lazy<secp256k1::Secp256k1<secp256k1::All>> =
Lazy::new(secp256k1::Secp256k1::new);

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum KeyType {
Expand Down Expand Up @@ -419,7 +420,7 @@ impl Eq for ED25519SecretKey {}
#[derive(Clone, Eq, PartialEq, Debug)]
pub enum SecretKey {
ED25519(ED25519SecretKey),
SECP256K1(secp256k1::key::SecretKey),
SECP256K1(secp256k1::SecretKey),
}

impl SecretKey {
Expand All @@ -437,7 +438,7 @@ impl SecretKey {
SecretKey::ED25519(ED25519SecretKey(keypair.to_bytes()))
}
KeyType::SECP256K1 => {
SecretKey::SECP256K1(secp256k1::key::SecretKey::new(&SECP256K1, &mut OsRng))
SecretKey::SECP256K1(secp256k1::SecretKey::new(&mut secp256k1::rand::rngs::OsRng))
}
}
}
Expand All @@ -450,13 +451,11 @@ impl SecretKey {
}

SecretKey::SECP256K1(secret_key) => {
let signature = SECP256K1
.sign_recoverable(
&secp256k1::Message::from_slice(data).expect("32 bytes"),
secret_key,
)
.expect("Failed to sign");
let (rec_id, data) = signature.serialize_compact(&SECP256K1);
let signature = SECP256K1.sign_ecdsa_recoverable(
&secp256k1::Message::from_slice(data).expect("32 bytes"),
secret_key,
);
let (rec_id, data) = signature.serialize_compact();
let mut buf = [0; 65];
buf[0..64].copy_from_slice(&data[0..64]);
buf[64] = rec_id.to_i32() as u8;
Expand All @@ -471,9 +470,8 @@ impl SecretKey {
secret_key.0[ed25519_dalek::SECRET_KEY_LENGTH..].try_into().unwrap(),
)),
SecretKey::SECP256K1(secret_key) => {
let pk =
secp256k1::key::PublicKey::from_secret_key(&SECP256K1, secret_key).unwrap();
let serialized = pk.serialize_vec(&SECP256K1, false);
let pk = secp256k1::PublicKey::from_secret_key(&SECP256K1, secret_key);
let serialized = pk.serialize_uncompressed();
let mut public_key = Secp256K1PublicKey([0; 64]);
public_key.0.copy_from_slice(&serialized[1..65]);
PublicKey::SECP256K1(public_key)
Expand Down Expand Up @@ -530,7 +528,7 @@ impl FromStr for SecretKey {
});
}
Ok(Self::SECP256K1(
secp256k1::key::SecretKey::from_slice(&SECP256K1, &array)
secp256k1::SecretKey::from_slice(&array)
.map_err(|err| Self::Err::InvalidData { error_message: err.to_string() })?,
))
}
Expand Down Expand Up @@ -600,22 +598,21 @@ impl Secp256K1Signature {
&self,
msg: [u8; 32],
) -> Result<Secp256K1PublicKey, crate::errors::ParseSignatureError> {
let recoverable_sig = secp256k1::RecoverableSignature::from_compact(
&SECP256K1,
let recoverable_sig = secp256k1::ecdsa::RecoverableSignature::from_compact(
&self.0[0..64],
secp256k1::RecoveryId::from_i32(i32::from(self.0[64])).unwrap(),
secp256k1::ecdsa::RecoveryId::from_i32(i32::from(self.0[64])).unwrap(),
)
.map_err(|err| crate::errors::ParseSignatureError::InvalidData {
error_message: err.to_string(),
})?;
let msg = Message::from(msg);
let msg = Message::from_slice(&msg).unwrap();

let res = SECP256K1
.recover(&msg, &recoverable_sig)
.recover_ecdsa(&msg, &recoverable_sig)
.map_err(|err| crate::errors::ParseSignatureError::InvalidData {
error_message: err.to_string(),
})?
.serialize_vec(&SECP256K1, false);
.serialize_uncompressed();

// Can not fail
let pk = Secp256K1PublicKey::try_from(&res[1..65]).unwrap();
Expand Down Expand Up @@ -733,24 +730,23 @@ impl Signature {
}
}
(Signature::SECP256K1(signature), PublicKey::SECP256K1(public_key)) => {
let rsig = secp256k1::RecoverableSignature::from_compact(
&SECP256K1,
let rsig = secp256k1::ecdsa::RecoverableSignature::from_compact(
&signature.0[0..64],
secp256k1::RecoveryId::from_i32(i32::from(signature.0[64])).unwrap(),
secp256k1::ecdsa::RecoveryId::from_i32(i32::from(signature.0[64])).unwrap(),
)
.unwrap();
let sig = rsig.to_standard(&SECP256K1);
let sig = rsig.to_standard();
let pdata: [u8; 65] = {
// code borrowed from https://github.com/openethereum/openethereum/blob/98b7c07171cd320f32877dfa5aa528f585dc9a72/ethkey/src/signature.rs#L210
let mut temp = [4u8; 65];
temp[1..65].copy_from_slice(&public_key.0);
temp
};
SECP256K1
.verify(
.verify_ecdsa(
&secp256k1::Message::from_slice(data).expect("32 bytes"),
&sig,
&secp256k1::key::PublicKey::from_slice(&SECP256K1, &pdata).unwrap(),
&secp256k1::PublicKey::from_slice(&pdata).unwrap(),
)
.is_ok()
}
Expand Down Expand Up @@ -940,18 +936,18 @@ mod tests {

let sk = SecretKey::from_seed(KeyType::SECP256K1, "test");
let pk = sk.public_key();
let expected = "\"secp256k1:BtJtBjukUQbcipnS78adSwUKE38sdHnk7pTNZH7miGXfodzUunaAcvY43y37nm7AKbcTQycvdgUzFNWsd7dgPZZ\"";
let expected = "\"secp256k1:5ftgm7wYK5gtVqq1kxMGy7gSudkrfYCbpsjL6sH1nwx2oj5NR2JktohjzB6fbEhhRERQpiwJcpwnQjxtoX3GS3cQ\"";
assert_eq!(serde_json::to_string(&pk).unwrap(), expected);
assert_eq!(pk, serde_json::from_str(expected).unwrap());
let pk2: PublicKey = pk.to_string().parse().unwrap();
assert_eq!(pk, pk2);

let expected = "\"secp256k1:9ZNzLxNff6ohoFFGkbfMBAFpZgD7EPoWeiuTpPAeeMRV\"";
let expected = "\"secp256k1:X4ETFKtQkSGVoZEnkn7bZ3LyajJaK2b3eweXaKmynGx\"";
assert_eq!(serde_json::to_string(&sk).unwrap(), expected);
assert_eq!(sk, serde_json::from_str(expected).unwrap());

let signature = sk.sign(&data);
let expected = "\"secp256k1:7iA75xRmHw17MbUkSpHxBHFVTuJW6jngzbuJPJutwb3EAwVw21wrjpMHU7fFTAqH7D3YEma8utCdvdtsqcAWqnC7r\"";
let expected = "\"secp256k1:5N5CB9H1dmB9yraLGCo4ZCQTcF24zj4v2NT14MHdH3aVhRoRXrX3AhprHr2w6iXNBZDmjMS1Ntzjzq8Bv6iBvwth6\"";
assert_eq!(serde_json::to_string(&signature).unwrap(), expected);
assert_eq!(signature, serde_json::from_str(expected).unwrap());
let signature_str: String = signature.to_string();
Expand Down
12 changes: 5 additions & 7 deletions core/crypto/src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use rand::rngs::StdRng;
use secp256k1::rand::SeedableRng;

use crate::signature::{
ED25519PublicKey, ED25519SecretKey, KeyType, PublicKey, SecretKey, SECP256K1,
};
use crate::signature::{ED25519PublicKey, ED25519SecretKey, KeyType, PublicKey, SecretKey};
use crate::{InMemorySigner, Signature};
use near_account_id::AccountId;

Expand All @@ -16,13 +14,13 @@ fn ed25519_key_pair_from_seed(seed: &str) -> ed25519_dalek::Keypair {
ed25519_dalek::Keypair { secret, public }
}

fn secp256k1_secret_key_from_seed(seed: &str) -> secp256k1::key::SecretKey {
fn secp256k1_secret_key_from_seed(seed: &str) -> secp256k1::SecretKey {
let seed_bytes = seed.as_bytes();
let len = std::cmp::min(32, seed_bytes.len());
let mut seed: [u8; 32] = [b' '; 32];
seed[..len].copy_from_slice(&seed_bytes[..len]);
let mut rng: StdRng = rand::SeedableRng::from_seed(seed);
secp256k1::key::SecretKey::new(&SECP256K1, &mut rng)
let mut rng = secp256k1::rand::rngs::StdRng::from_seed(seed);
secp256k1::SecretKey::new(&mut rng)
}

impl PublicKey {
Expand Down

0 comments on commit 5a1f8c6

Please sign in to comment.