mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-18 10:41:01 +00:00
Additional externs for ecdsa recovery and keccak (#1583)
* Additional externs for ecdsa recovery and keccak * Update core/executor/src/wasm_executor.rs Co-Authored-By: gavofyork <github@gavwood.com> * Update core/executor/src/wasm_executor.rs Co-Authored-By: gavofyork <github@gavwood.com> * Fix grumble * Grumble.
This commit is contained in:
@@ -12,7 +12,8 @@ sr-std = { path = "../sr-std", default-features = false }
|
||||
substrate-primitives = { path = "../primitives", default-features = false }
|
||||
parity-codec = { version = "2.2", default-features = false }
|
||||
hash-db = { version = "0.9", default-features = false }
|
||||
|
||||
libsecp256k1 = { version = "0.2.1", optional = true }
|
||||
tiny-keccak = { version = "1.4.2", optional = true }
|
||||
environmental = { version = "~1.0", optional = true }
|
||||
substrate-state-machine = { path = "../state-machine", optional = true }
|
||||
substrate-trie = { path = "../trie", optional = true }
|
||||
@@ -27,7 +28,9 @@ std = [
|
||||
"hash-db/std",
|
||||
"environmental",
|
||||
"substrate-state-machine",
|
||||
"substrate-trie"
|
||||
"substrate-trie",
|
||||
"libsecp256k1",
|
||||
"tiny-keccak"
|
||||
]
|
||||
nightly = []
|
||||
strict = []
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
#![cfg_attr(feature = "std", doc = "Substrate runtime standard library as compiled when linked with Rust's standard library.")]
|
||||
#![cfg_attr(not(feature = "std"), doc = "Substrate's runtime standard library as compiled without Rust's standard library.")]
|
||||
|
||||
pub enum EcdsaVerifyError {
|
||||
BadRS,
|
||||
BadV,
|
||||
BadSignature,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
include!("../with_std.rs");
|
||||
|
||||
|
||||
@@ -24,10 +24,14 @@ extern crate substrate_state_machine;
|
||||
extern crate substrate_trie as trie;
|
||||
extern crate hash_db;
|
||||
|
||||
extern crate tiny_keccak;
|
||||
extern crate secp256k1;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub extern crate parity_codec as codec;
|
||||
// re-export hashing functions.
|
||||
pub use primitives::{blake2_256, twox_128, twox_256, ed25519};
|
||||
pub use tiny_keccak::keccak256 as keccak_256;
|
||||
|
||||
pub use primitives::{Blake2Hasher};
|
||||
// Switch to this after PoC-3
|
||||
@@ -200,6 +204,18 @@ pub fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) ->
|
||||
ed25519::verify(sig, msg, pubkey)
|
||||
}
|
||||
|
||||
/// Verify and recover a SECP256k1 ECDSA signature.
|
||||
/// - `sig` is passed in RSV format. V should be either 0/1 or 27/28.
|
||||
/// - returns `Err` if the signatue is bad, otherwise the 64-byte pubkey (doesn't include the 0x04 prefix).
|
||||
pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> {
|
||||
let rs = secp256k1::Signature::parse_slice(&sig[0..64]).map_err(|_| EcdsaVerifyError::BadRS)?;
|
||||
let v = secp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8).map_err(|_| EcdsaVerifyError::BadV)?;
|
||||
let pubkey = secp256k1::recover(&secp256k1::Message::parse(msg), &rs, &v).map_err(|_| EcdsaVerifyError::BadSignature)?;
|
||||
let mut res = [0u8; 64];
|
||||
res.copy_from_slice(&pubkey.serialize()[1..65]);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Execute the given closure with global function available whose functionality routes into the
|
||||
/// externalities `ext`. Forwards the value that the closure returns.
|
||||
// NOTE: need a concrete hasher here due to limitations of the `environmental!` macro, otherwise a type param would have been fine I think.
|
||||
|
||||
@@ -91,8 +91,11 @@ extern "C" {
|
||||
fn ext_blake2_256(data: *const u8, len: u32, out: *mut u8);
|
||||
fn ext_twox_128(data: *const u8, len: u32, out: *mut u8);
|
||||
fn ext_twox_256(data: *const u8, len: u32, out: *mut u8);
|
||||
fn ext_keccak_256(data: *const u8, len: u32, out: *mut u8);
|
||||
/// Note: ext_ed25519_verify returns 0 if the signature is correct, nonzero otherwise.
|
||||
fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32;
|
||||
/// Note: ext_secp256k1_ecdsa_recover returns 0 if the signature is correct, nonzero otherwise.
|
||||
fn ext_secp256k1_ecdsa_recover(msg_data: *const u8, sig_data: *const u8, pubkey_data: *mut u8) -> u32;
|
||||
}
|
||||
|
||||
/// Ensures we use the right crypto when calling into native
|
||||
@@ -343,6 +346,15 @@ pub fn blake2_256(data: &[u8]) -> [u8; 32] {
|
||||
result
|
||||
}
|
||||
|
||||
/// Conduct a 256-bit Keccak hash.
|
||||
pub fn keccak_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
unsafe {
|
||||
ext_keccak_256(data.as_ptr(), data.len() as u32, result.as_mut_ptr());
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Conduct four XX hashes to give a 256-bit result.
|
||||
pub fn twox_256(data: &[u8]) -> [u8; 32] {
|
||||
let mut result: [u8; 32] = Default::default();
|
||||
@@ -368,6 +380,22 @@ pub fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) ->
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify and recover a SECP256k1 ECDSA signature.
|
||||
/// - `sig` is passed in RSV format. V should be either 0/1 or 27/28.
|
||||
/// - returns `None` if the signatue is bad, the 64-byte pubkey (doesn't include the 0x04 prefix).
|
||||
pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> {
|
||||
let mut pubkey = [0u8; 64];
|
||||
match unsafe {
|
||||
ext_secp256k1_ecdsa_recover(msg.as_ptr(), sig.as_ptr(), pubkey.as_mut_ptr())
|
||||
} {
|
||||
0 => Ok(pubkey),
|
||||
1 => Err(EcdsaVerifyError::BadRS),
|
||||
2 => Err(EcdsaVerifyError::BadV),
|
||||
3 => Err(EcdsaVerifyError::BadSignature),
|
||||
_ => unreachable!("`ext_secp256k1_ecdsa_recover` only returns 0, 1, 2 or 3; qed"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for things which can be printed.
|
||||
pub trait Printable {
|
||||
fn print(self);
|
||||
|
||||
Reference in New Issue
Block a user