Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
chore: bump crypto deps (#2260)
Browse files Browse the repository at this point in the history
* chore(core): bump k256

* fix: use correct recovery api

* fix(signers): use correct apis

* chore(signers): bump elliptic curve

* feat: use PreHashSigner

* feat: bump yubihsm and adjust for breakages

* chore: clippy
  • Loading branch information
gakonst authored Mar 15, 2023
1 parent 516dfcf commit 18a049b
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 305 deletions.
283 changes: 141 additions & 142 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions ethers-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ arrayvec = { version = "0.7.2", default-features = false }
rlp-derive = { version = "0.1.0", default-features = false }

# crypto
elliptic-curve = { version = "0.12.3", default-features = false }
elliptic-curve = { version = "0.13.2", default-features = false }
generic-array = { version = "0.14.6", default-features = false }
k256 = { version = "0.11", default-features = false, features = ["keccak256", "ecdsa", "std"] }
k256 = { version = "0.13.0", default-features = false, features = ["ecdsa", "std"] }
rand = { version = "0.8.5", default-features = false }
tiny-keccak = { version = "2.0.2", default-features = false }

Expand Down
18 changes: 10 additions & 8 deletions ethers-core/src/types/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use elliptic_curve::{consts::U32, sec1::ToEncodedPoint};
use generic_array::GenericArray;
use k256::{
ecdsa::{
recoverable::{Id as RecoveryId, Signature as RecoverableSignature},
Error as K256SignatureError, Signature as K256Signature,
Error as K256SignatureError, RecoveryId, Signature as RecoverableSignature,
Signature as K256Signature, VerifyingKey,
},
PublicKey as K256PublicKey,
};
Expand Down Expand Up @@ -115,9 +115,12 @@ impl Signature {
RecoveryMessage::Hash(hash) => hash,
};

let (recoverable_sig, _recovery_id) = self.as_signature()?;
let verify_key = recoverable_sig
.recover_verifying_key_from_digest_bytes(message_hash.as_ref().into())?;
let (recoverable_sig, recovery_id) = self.as_signature()?;
let verify_key = VerifyingKey::recover_from_prehash(
message_hash.as_ref(),
&recoverable_sig,
recovery_id,
)?;

let public_key = K256PublicKey::from(&verify_key);
let public_key = public_key.to_encoded_point(/* compress = */ false);
Expand All @@ -137,8 +140,7 @@ impl Signature {
self.s.to_big_endian(&mut s_bytes);
let gar: &GenericArray<u8, U32> = GenericArray::from_slice(&r_bytes);
let gas: &GenericArray<u8, U32> = GenericArray::from_slice(&s_bytes);
let sig = K256Signature::from_scalars(*gar, *gas)?;
RecoverableSignature::new(&sig, recovery_id)?
K256Signature::from_scalars(*gar, *gas)?
};

Ok((signature, recovery_id))
Expand All @@ -147,7 +149,7 @@ impl Signature {
/// Retrieve the recovery ID.
pub fn recovery_id(&self) -> Result<RecoveryId, SignatureError> {
let standard_v = normalize_recovery_id(self.v);
Ok(RecoveryId::new(standard_v)?)
Ok(RecoveryId::from_byte(standard_v).expect("normalized recovery id always valid"))
}

/// Copies and serializes `self` into a new `Vec` with the recovery id included
Expand Down
4 changes: 3 additions & 1 deletion ethers-core/src/utils/anvil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{
types::{Address, Chain},
utils::{secret_key_to_address, unused_ports},
};
use generic_array::GenericArray;
use k256::{ecdsa::SigningKey, SecretKey as K256SecretKey};
use std::{
io::{BufRead, BufReader},
Expand Down Expand Up @@ -278,7 +279,8 @@ impl Anvil {
if is_private_key && line.starts_with('(') {
let key_str = &line[6..line.len() - 1];
let key_hex = hex::decode(key_str).expect("could not parse as hex");
let key = K256SecretKey::from_be_bytes(&key_hex).expect("did not get private key");
let key = K256SecretKey::from_bytes(&GenericArray::clone_from_slice(&key_hex))
.expect("did not get private key");
addresses.push(secret_key_to_address(&SigningKey::from(&key)));
private_keys.push(key);
}
Expand Down
4 changes: 3 additions & 1 deletion ethers-core/src/utils/ganache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{
types::Address,
utils::{secret_key_to_address, unused_ports},
};
use generic_array::GenericArray;
use k256::{ecdsa::SigningKey, SecretKey as K256SecretKey};
use std::{
io::{BufRead, BufReader},
Expand Down Expand Up @@ -205,7 +206,8 @@ impl Ganache {
if is_private_key && line.starts_with('(') {
let key_str = &line[6..line.len() - 1];
let key_hex = hex::decode(key_str).expect("could not parse as hex");
let key = K256SecretKey::from_be_bytes(&key_hex).expect("did not get private key");
let key = K256SecretKey::from_bytes(&GenericArray::clone_from_slice(&key_hex))
.expect("did not get private key");
addresses.push(secret_key_to_address(&SigningKey::from(&key)));
private_keys.push(key);
}
Expand Down
5 changes: 2 additions & 3 deletions ethers-core/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ pub use rlp;
pub use hex;

use crate::types::{Address, Bytes, ParseI256Error, H256, I256, U256, U64};
use elliptic_curve::sec1::ToEncodedPoint;
use ethabi::ethereum_types::FromDecStrErr;
use k256::{ecdsa::SigningKey, PublicKey as K256PublicKey};
use k256::ecdsa::SigningKey;
use std::{
collections::HashMap,
convert::{TryFrom, TryInto},
Expand Down Expand Up @@ -385,7 +384,7 @@ pub fn get_create2_address_from_hash(

/// Converts a K256 SigningKey to an Ethereum Address
pub fn secret_key_to_address(secret_key: &SigningKey) -> Address {
let public_key = K256PublicKey::from(&secret_key.verifying_key());
let public_key = secret_key.verifying_key();
let public_key = public_key.to_encoded_point(/* compress = */ false);
let public_key = public_key.as_bytes();
debug_assert_eq!(public_key[0], 0x04);
Expand Down
3 changes: 2 additions & 1 deletion ethers-core/src/utils/moonbeam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use std::collections::BTreeMap;

use generic_array::GenericArray;
use k256::SecretKey;

/// Returns the private developer keys <https://docs.moonbeam.network/builders/get-started/networks/moonbeam-dev/#pre-funded-development-accounts>
Expand Down Expand Up @@ -47,7 +48,7 @@ impl MoonbeamDev {
}

fn to_secret_key(s: &str) -> SecretKey {
SecretKey::from_be_bytes(&hex::decode(s).unwrap()).unwrap()
SecretKey::from_bytes(&GenericArray::clone_from_slice(&hex::decode(s).unwrap())).unwrap()
}

impl Default for MoonbeamDev {
Expand Down
6 changes: 3 additions & 3 deletions ethers-signers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ coins-bip39 = "0.8.1"
coins-ledger = { version = "0.7.1", default-features = false, optional = true }
hex = { version = "0.4.3", default-features = false, features = ["std"] }
async-trait = { version = "0.1.50", default-features = false }
elliptic-curve = { version = "0.12.3", default-features = false }
elliptic-curve = { version = "0.13.2", default-features = false }
sha2 = { version = "0.10.6", default-features = false }
rand = { version = "0.8.5", default-features = false }
yubihsm = { version = "0.41.0", features = ["secp256k1", "http", "usb"], optional = true }
yubihsm = { version = "0.42.0-pre.0", features = ["secp256k1", "http", "usb"], optional = true }
futures-util = { version = "^0.3", optional = true }
futures-executor = { version = "^0.3", optional = true }
semver = { version = "1.0.17", optional = true }
Expand All @@ -49,7 +49,7 @@ ethers-contract-derive = { version = "^2.0.0", path = "../ethers-contract/ethers
ethers-derive-eip712 = { version = "^2.0.0", path = "../ethers-core/ethers-derive-eip712" }

serde_json = { version = "1.0.64" }
yubihsm = { version = "0.41.0", features = ["secp256k1", "usb", "mockhsm"] }
yubihsm = { version = "0.42.0-pre.0", features = ["secp256k1", "usb", "mockhsm"] }
tokio = { version = "1.18", default-features = false, features = ["macros", "rt"] }
tempfile = "3.4.0"
tracing-subscriber = "0.3.16"
Expand Down
15 changes: 6 additions & 9 deletions ethers-signers/src/aws/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rusoto_kms::{
use tracing::{debug, instrument, trace};

mod utils;
use utils::{apply_eip155, rsig_to_ethsig, verifying_key_to_address};
use utils::{apply_eip155, verifying_key_to_address};

/// An ethers Signer that uses keys held in Amazon AWS KMS.
///
Expand Down Expand Up @@ -57,7 +57,7 @@ impl std::fmt::Debug for AwsSigner {
f.debug_struct("AwsSigner")
.field("key_id", &self.key_id)
.field("chain_id", &self.chain_id)
.field("pubkey", &hex::encode(self.pubkey.to_bytes()))
.field("pubkey", &hex::encode(self.pubkey.to_sec1_bytes()))
.field("address", &self.address)
.finish()
}
Expand Down Expand Up @@ -165,7 +165,7 @@ impl AwsSigner {

debug!(
"Instantiated AWS signer with pubkey 0x{} and address 0x{}",
hex::encode(pubkey.to_bytes()),
hex::encode(pubkey.to_sec1_bytes()),
hex::encode(address)
);

Expand Down Expand Up @@ -211,10 +211,8 @@ impl AwsSigner {
chain_id: u64,
) -> Result<EthSig, AwsSignerError> {
let sig = self.sign_digest(digest.into()).await?;

let sig = utils::rsig_from_digest_bytes_trial_recovery(&sig, digest.into(), &self.pubkey);

let mut sig = rsig_to_ethsig(&sig);
let mut sig =
utils::sig_from_digest_bytes_trial_recovery(&sig, digest.into(), &self.pubkey);
apply_eip155(&mut sig, chain_id);
Ok(sig)
}
Expand Down Expand Up @@ -255,8 +253,7 @@ impl super::Signer for AwsSigner {
payload.encode_eip712().map_err(|e| Self::Error::Eip712Error(e.to_string()))?;

let sig = self.sign_digest(digest).await?;
let sig = utils::rsig_from_digest_bytes_trial_recovery(&sig, digest, &self.pubkey);
let sig = rsig_to_ethsig(&sig);
let sig = utils::sig_from_digest_bytes_trial_recovery(&sig, digest.into(), &self.pubkey);

Ok(sig)
}
Expand Down
50 changes: 20 additions & 30 deletions ethers-signers/src/aws/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ use std::convert::TryFrom;

use ethers_core::{
k256::{
ecdsa::{
recoverable::{Id, Signature as RSig},
Signature as KSig, VerifyingKey,
},
elliptic_curve::sec1::ToEncodedPoint,
ecdsa::{RecoveryId, Signature as RSig, Signature as KSig, VerifyingKey},
FieldBytes,
},
types::{Address, Signature as EthSig, U256},
Expand All @@ -20,40 +16,34 @@ use rusoto_kms::{GetPublicKeyResponse, SignResponse};

use crate::aws::AwsSignerError;

/// Converts a recoverable signature to an ethers signature
pub(super) fn rsig_to_ethsig(sig: &RSig) -> EthSig {
let v: u8 = sig.recovery_id().into();
let v = (v + 27) as u64;
let r_bytes: FieldBytes = sig.r().into();
let s_bytes: FieldBytes = sig.s().into();
let r = U256::from_big_endian(r_bytes.as_slice());
let s = U256::from_big_endian(s_bytes.as_slice());
EthSig { r, s, v }
}

/// Makes a trial recovery to check whether an RSig corresponds to a known
/// `VerifyingKey`
fn check_candidate(sig: &RSig, digest: [u8; 32], vk: &VerifyingKey) -> bool {
if let Ok(key) = sig.recover_verifying_key_from_digest_bytes(digest.as_ref().into()) {
key == *vk
} else {
false
}
fn check_candidate(
sig: &RSig,
recovery_id: RecoveryId,
digest: [u8; 32],
vk: &VerifyingKey,
) -> bool {
VerifyingKey::recover_from_prehash(digest.as_slice(), sig, recovery_id)
.map(|key| key == *vk)
.unwrap_or(false)
}

/// Recover an rsig from a signature under a known key by trial/error
pub(super) fn rsig_from_digest_bytes_trial_recovery(
pub(super) fn sig_from_digest_bytes_trial_recovery(
sig: &KSig,
digest: [u8; 32],
vk: &VerifyingKey,
) -> RSig {
let sig_0 = RSig::new(sig, Id::new(0).unwrap()).unwrap();
let sig_1 = RSig::new(sig, Id::new(1).unwrap()).unwrap();
) -> EthSig {
let r_bytes: FieldBytes = sig.r().into();
let s_bytes: FieldBytes = sig.s().into();
let r = U256::from_big_endian(r_bytes.as_slice());
let s = U256::from_big_endian(s_bytes.as_slice());

if check_candidate(&sig_0, digest, vk) {
sig_0
} else if check_candidate(&sig_1, digest, vk) {
sig_1
if check_candidate(&sig, RecoveryId::from_byte(0).unwrap(), digest, vk) {
EthSig { r, s, v: 0 }
} else if check_candidate(&sig, RecoveryId::from_byte(1).unwrap(), digest, vk) {
EthSig { r, s, v: 1 }
} else {
panic!("bad sig");
}
Expand Down
80 changes: 0 additions & 80 deletions ethers-signers/src/wallet/hash.rs

This file was deleted.

Loading

0 comments on commit 18a049b

Please sign in to comment.