mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-25 08:15:44 +00:00
Refactor key management (#3296)
* Add Call type to extensible transactions. Cleanup some naming * Merge Resource and BlockExhausted into just Exhausted * Fix * Another fix * Call * Some fixes * Fix srml tests. * Fix all tests. * Refactor crypto so each application of it has its own type. * Introduce new AuthorityProvider API into Aura This will eventually allow for dynamic determination of authority keys and avoid having to set them directly on CLI. * Introduce authority determinator for Babe. Experiment with modular consensus API. * Work in progress to introduce KeyTypeId and avoid polluting API with validator IDs * Finish up drafting imonline * Rework offchain workers API. * Rework API implementation. * Make it compile for wasm, simplify app_crypto. * Fix compilation of im-online. * Fix compilation of im-online. * Fix more compilation errors. * Make it compile. * Fixing tests. * Rewrite `keystore` * Fix session tests * Bring back `TryFrom`'s' * Fix `srml-grandpa` * Fix `srml-aura` * Fix consensus babe * More fixes * Make service generate keys from dev_seed * Build fixes * Remove offchain tests * More fixes and cleanups * Fixes finality grandpa * Fix `consensus-aura` * Fix cli * Fix `node-cli` * Fix chain_spec builder * Fix doc tests * Add authority getter for grandpa. * Test fix * Fixes * Make keystore accessible from the runtime * Move app crypto to its own crate * Update `Cargo.lock` * Make the crypto stuff usable from the runtime * Adds some runtime crypto tests * Use last finalized block for grandpa authority * Fix warning * Adds `SessionKeys` runtime api * Remove `FinalityPair` and `ConsensusPair` * Minor governance tweaks to get it inline with docs. * Make the governance be up to date with the docs. * Build fixes. * Generate the inital session keys * Failing keystore is a hard error * Make babe work again * Fix grandpa * Fix tests * Disable `keystore` in consensus critical stuff * Build fix. * ImOnline supports multiple authorities at once. * Update core/application-crypto/src/ed25519.rs * Merge branch 'master' into gav-in-progress * Remove unneeded code for now. * Some `session` testing * Support querying the public keys * Cleanup offchain * Remove warnings * More cleanup * Apply suggestions from code review Co-Authored-By: Benjamin Kampmann <ben.kampmann@googlemail.com> * More cleanups * JSONRPC API for setting keys. Also, rename traits::KeyStore* -> traits::BareCryptoStore* * Bad merge * Fix integration tests * Fix test build * Test fix * Fixes * Warnings * Another warning * Bump version.
This commit is contained in:
@@ -33,12 +33,11 @@ use rstd::vec::Vec;
|
||||
pub use codec;
|
||||
|
||||
pub use primitives::Blake2Hasher;
|
||||
use primitives::offchain::{
|
||||
Timestamp,
|
||||
HttpRequestId, HttpRequestStatus, HttpError,
|
||||
CryptoKind, CryptoKey,
|
||||
StorageKind,
|
||||
OpaqueNetworkState,
|
||||
use primitives::{
|
||||
crypto::KeyTypeId, ed25519, sr25519,
|
||||
offchain::{
|
||||
Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState,
|
||||
},
|
||||
};
|
||||
|
||||
/// Error verifying ECDSA signature
|
||||
@@ -69,7 +68,7 @@ macro_rules! export_api {
|
||||
$( #[$attr:meta] )*
|
||||
fn $name:ident
|
||||
$(< $( $g_name:ident $( : $g_ty:path )? ),+ >)?
|
||||
( $( $arg:ident : $arg_ty:ty ),* )
|
||||
( $( $arg:ident : $arg_ty:ty ),* $(,)? )
|
||||
$( -> $ret:ty )?
|
||||
$( where $( $w_name:path : $w_ty:path ),+ )?;
|
||||
)*
|
||||
@@ -200,11 +199,45 @@ export_api! {
|
||||
|
||||
export_api! {
|
||||
pub(crate) trait CryptoApi {
|
||||
/// Verify a ed25519 signature.
|
||||
fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool;
|
||||
/// Returns all ed25519 public keys for the given key id from the keystore.
|
||||
fn ed25519_public_keys(id: KeyTypeId) -> Vec<ed25519::Public>;
|
||||
/// Generate an ed22519 key for the given key type and store it in the keystore.
|
||||
///
|
||||
/// Returns the raw public key.
|
||||
fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public;
|
||||
/// Sign the given `msg` with the ed25519 key that corresponds to the given public key and
|
||||
/// key type in the keystore.
|
||||
///
|
||||
/// Returns the raw signature.
|
||||
fn ed25519_sign<M: AsRef<[u8]>>(
|
||||
id: KeyTypeId,
|
||||
pubkey: &ed25519::Public,
|
||||
msg: &M,
|
||||
) -> Option<ed25519::Signature>;
|
||||
/// Verify an ed25519 signature.
|
||||
///
|
||||
/// Returns `true` when the verification in successful.
|
||||
fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool;
|
||||
|
||||
/// Returns all sr25519 public keys for the given key id from the keystore.
|
||||
fn sr25519_public_keys(id: KeyTypeId) -> Vec<sr25519::Public>;
|
||||
/// Generate an sr22519 key for the given key type and store it in the keystore.
|
||||
///
|
||||
/// Returns the raw public key.
|
||||
fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public;
|
||||
/// Sign the given `msg` with the sr25519 key that corresponds to the given public key and
|
||||
/// key type in the keystore.
|
||||
///
|
||||
/// Returns the raw signature.
|
||||
fn sr25519_sign<M: AsRef<[u8]>>(
|
||||
id: KeyTypeId,
|
||||
pubkey: &sr25519::Public,
|
||||
msg: &M,
|
||||
) -> Option<sr25519::Signature>;
|
||||
/// Verify an sr25519 signature.
|
||||
fn sr25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool;
|
||||
///
|
||||
/// Returns `true` when the verification in successful.
|
||||
fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool;
|
||||
|
||||
/// Verify and recover a SECP256k1 ECDSA signature.
|
||||
/// - `sig` is passed in RSV format. V should be either 0/1 or 27/28.
|
||||
@@ -245,42 +278,6 @@ export_api! {
|
||||
/// Returns information about the local node's network state.
|
||||
fn network_state() -> Result<OpaqueNetworkState, ()>;
|
||||
|
||||
/// Returns the currently configured authority public key, if available.
|
||||
fn pubkey(key: CryptoKey) -> Result<Vec<u8>, ()>;
|
||||
|
||||
/// Create new key(pair) for signing/encryption/decryption.
|
||||
///
|
||||
/// Returns an error if given crypto kind is not supported.
|
||||
fn new_crypto_key(crypto: CryptoKind) -> Result<CryptoKey, ()>;
|
||||
|
||||
/// Encrypt a piece of data using given crypto key.
|
||||
///
|
||||
/// If `key` is `None`, it will attempt to use current authority key.
|
||||
///
|
||||
/// Returns an error if `key` is not available or does not exist.
|
||||
fn encrypt(key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()>;
|
||||
|
||||
/// Decrypt a piece of data using given crypto key.
|
||||
///
|
||||
/// If `key` is `None`, it will attempt to use current authority key.
|
||||
///
|
||||
/// Returns an error if data cannot be decrypted or the `key` is not available or does not exist.
|
||||
fn decrypt(key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()>;
|
||||
|
||||
/// Sign a piece of data using given crypto key.
|
||||
///
|
||||
/// If `key` is `None`, it will attempt to use current authority key.
|
||||
///
|
||||
/// Returns an error if `key` is not available or does not exist.
|
||||
fn sign(key: CryptoKey, data: &[u8]) -> Result<Vec<u8>, ()>;
|
||||
|
||||
/// Verifies that `signature` for `msg` matches given `key`.
|
||||
///
|
||||
/// Returns an `Ok` with `true` in case it does, `false` in case it doesn't.
|
||||
/// Returns an error in case the key is not available or does not exist or the parameters
|
||||
/// lengths are incorrect.
|
||||
fn verify(key: CryptoKey, msg: &[u8], signature: &[u8]) -> Result<bool, ()>;
|
||||
|
||||
/// Returns current UNIX timestamp (in millis)
|
||||
fn timestamp() -> Timestamp;
|
||||
|
||||
|
||||
@@ -15,24 +15,19 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use primitives::{
|
||||
blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher,
|
||||
sr25519, Pair
|
||||
blake2_128, blake2_256, twox_128, twox_256, twox_64, ed25519, Blake2Hasher, sr25519, Pair,
|
||||
};
|
||||
// Switch to this after PoC-3
|
||||
// pub use primitives::BlakeHasher;
|
||||
pub use substrate_state_machine::{
|
||||
Externalities,
|
||||
BasicExternalities,
|
||||
TestExternalities,
|
||||
ChildStorageKey
|
||||
Externalities, BasicExternalities, TestExternalities, ChildStorageKey,
|
||||
};
|
||||
|
||||
use environmental::environmental;
|
||||
use primitives::{offchain, hexdisplay::HexDisplay, H256};
|
||||
use trie::{TrieConfiguration, trie_types::Layout};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, convert::TryFrom};
|
||||
|
||||
environmental!(ext: trait Externalities<Blake2Hasher>);
|
||||
|
||||
@@ -208,12 +203,82 @@ impl OtherApi for () {
|
||||
}
|
||||
|
||||
impl CryptoApi for () {
|
||||
fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
|
||||
ed25519::Pair::verify_weak(sig, msg, pubkey)
|
||||
fn ed25519_public_keys(id: KeyTypeId) -> Vec<ed25519::Public> {
|
||||
ext::with(|ext| {
|
||||
ext.keystore()
|
||||
.expect("No `keystore` associated for the current context!")
|
||||
.write()
|
||||
.ed25519_public_keys(id)
|
||||
}).expect("`ed25519_public_keys` cannot be called outside of an Externalities-provided environment.")
|
||||
}
|
||||
|
||||
fn sr25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
|
||||
sr25519::Pair::verify_weak(sig, msg, pubkey)
|
||||
fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public {
|
||||
ext::with(|ext| {
|
||||
ext.keystore()
|
||||
.expect("No `keystore` associated for the current context!")
|
||||
.write()
|
||||
.ed25519_generate_new(id, seed)
|
||||
.expect("`ed25519_generate` failed")
|
||||
}).expect("`ed25519_generate` cannot be called outside of an Externalities-provided environment.")
|
||||
}
|
||||
|
||||
fn ed25519_sign<M: AsRef<[u8]>>(
|
||||
id: KeyTypeId,
|
||||
pubkey: &ed25519::Public,
|
||||
msg: &M,
|
||||
) -> Option<ed25519::Signature> {
|
||||
let pub_key = ed25519::Public::try_from(pubkey.as_ref()).ok()?;
|
||||
|
||||
ext::with(|ext| {
|
||||
ext.keystore()
|
||||
.expect("No `keystore` associated for the current context!")
|
||||
.read()
|
||||
.ed25519_key_pair(id, &pub_key)
|
||||
.map(|k| k.sign(msg.as_ref()).into())
|
||||
}).expect("`ed25519_sign` cannot be called outside of an Externalities-provided environment.")
|
||||
}
|
||||
|
||||
fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool {
|
||||
ed25519::Pair::verify(sig, msg, pubkey)
|
||||
}
|
||||
|
||||
fn sr25519_public_keys(id: KeyTypeId) -> Vec<sr25519::Public> {
|
||||
ext::with(|ext| {
|
||||
ext.keystore()
|
||||
.expect("No `keystore` associated for the current context!")
|
||||
.write()
|
||||
.sr25519_public_keys(id)
|
||||
}).expect("`sr25519_public_keys` cannot be called outside of an Externalities-provided environment.")
|
||||
}
|
||||
|
||||
fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public {
|
||||
ext::with(|ext| {
|
||||
ext.keystore()
|
||||
.expect("No `keystore` associated for the current context!")
|
||||
.write()
|
||||
.sr25519_generate_new(id, seed)
|
||||
.expect("`sr25519_generate` failed")
|
||||
}).expect("`sr25519_generate` cannot be called outside of an Externalities-provided environment.")
|
||||
}
|
||||
|
||||
fn sr25519_sign<M: AsRef<[u8]>>(
|
||||
id: KeyTypeId,
|
||||
pubkey: &sr25519::Public,
|
||||
msg: &M,
|
||||
) -> Option<sr25519::Signature> {
|
||||
let pub_key = sr25519::Public::try_from(pubkey.as_ref()).ok()?;
|
||||
|
||||
ext::with(|ext| {
|
||||
ext.keystore()
|
||||
.expect("No `keystore` associated for the current context!")
|
||||
.read()
|
||||
.sr25519_key_pair(id, &pub_key)
|
||||
.map(|k| k.sign(msg.as_ref()).into())
|
||||
}).expect("`sr25519_sign` cannot be called outside of an Externalities-provided environment.")
|
||||
}
|
||||
|
||||
fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool {
|
||||
sr25519::Pair::verify(sig, msg, pubkey)
|
||||
}
|
||||
|
||||
fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> {
|
||||
@@ -276,55 +341,6 @@ impl OffchainApi for () {
|
||||
}, "network_state can be called only in the offchain worker context")
|
||||
}
|
||||
|
||||
fn pubkey(key: offchain::CryptoKey) -> Result<Vec<u8>, ()> {
|
||||
with_offchain(|ext| {
|
||||
ext.pubkey(key)
|
||||
}, "authority_pubkey can be called only in the offchain worker context")
|
||||
}
|
||||
|
||||
fn new_crypto_key(crypto: offchain::CryptoKind) -> Result<offchain::CryptoKey, ()> {
|
||||
with_offchain(|ext| {
|
||||
ext.new_crypto_key(crypto)
|
||||
}, "new_crypto_key can be called only in the offchain worker context")
|
||||
}
|
||||
|
||||
fn encrypt(
|
||||
key: offchain::CryptoKey,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
with_offchain(|ext| {
|
||||
ext.encrypt(key, data)
|
||||
}, "encrypt can be called only in the offchain worker context")
|
||||
}
|
||||
|
||||
fn decrypt(
|
||||
key: offchain::CryptoKey,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
with_offchain(|ext| {
|
||||
ext.decrypt(key, data)
|
||||
}, "decrypt can be called only in the offchain worker context")
|
||||
}
|
||||
|
||||
fn sign(
|
||||
key: offchain::CryptoKey,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
with_offchain(|ext| {
|
||||
ext.sign(key, data)
|
||||
}, "sign can be called only in the offchain worker context")
|
||||
}
|
||||
|
||||
fn verify(
|
||||
key: offchain::CryptoKey,
|
||||
msg: &[u8],
|
||||
signature: &[u8],
|
||||
) -> Result<bool, ()> {
|
||||
with_offchain(|ext| {
|
||||
ext.verify(key, msg, signature)
|
||||
}, "verify can be called only in the offchain worker context")
|
||||
}
|
||||
|
||||
fn timestamp() -> offchain::Timestamp {
|
||||
with_offchain(|ext| {
|
||||
ext.timestamp()
|
||||
|
||||
+149
-197
@@ -19,8 +19,9 @@ pub use rstd;
|
||||
pub use rstd::{mem, slice};
|
||||
|
||||
use core::{intrinsics, panic::PanicInfo};
|
||||
use rstd::{vec::Vec, cell::Cell, convert::TryInto, convert::TryFrom};
|
||||
use rstd::{vec::Vec, cell::Cell, convert::TryInto};
|
||||
use primitives::{offchain, Blake2Hasher};
|
||||
use codec::Decode;
|
||||
|
||||
#[cfg(not(feature = "no_panic_handler"))]
|
||||
#[panic_handler]
|
||||
@@ -158,7 +159,7 @@ pub mod ext {
|
||||
(
|
||||
$(
|
||||
$( #[$attr:meta] )*
|
||||
fn $name:ident ( $( $arg:ident : $arg_ty:ty ),* ) $( -> $ret:ty )?;
|
||||
fn $name:ident ( $( $arg:ident : $arg_ty:ty ),* $(,)? ) $( -> $ret:ty )?;
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
@@ -352,25 +353,72 @@ pub mod ext {
|
||||
fn ext_twox_256(data: *const u8, len: u32, out: *mut u8);
|
||||
/// Keccak256 hash
|
||||
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.
|
||||
|
||||
/// Returns all `ed25519` public keys for the given key type from the keystore.
|
||||
fn ext_ed25519_public_keys(id: *const u8, result_len: *mut u32) -> *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
|
||||
pubkey_data: *const u8,
|
||||
) -> u32;
|
||||
/// Note: ext_sr25519_verify returns 0 if the signature is correct, nonzero otherwise.
|
||||
|
||||
/// Generate an `ed25519` key pair for the given key type id and store the public key
|
||||
/// in `out`.
|
||||
fn ext_ed25519_generate(id: *const u8, seed: *const u8, seed_len: u32, out: *mut u8);
|
||||
|
||||
/// Sign the given `msg` with the `ed25519` key pair that corresponds to then given key
|
||||
/// type id and public key. The raw signature is stored in `out`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `0` on success
|
||||
/// - nonezero if something failed, e.g. retrieving of the key.
|
||||
fn ext_ed25519_sign(
|
||||
id: *const u8,
|
||||
pubkey: *const u8,
|
||||
msg: *const u8,
|
||||
msg_len: u32,
|
||||
out: *mut u8,
|
||||
) -> u32;
|
||||
|
||||
/// Returns all `sr25519` public keys for the given key type from the keystore.
|
||||
fn ext_sr25519_public_keys(id: *const u8, result_len: *mut u32) -> *mut u8;
|
||||
|
||||
/// Note: `ext_sr25519_verify` returns 0 if the signature is correct, nonzero otherwise.
|
||||
fn ext_sr25519_verify(
|
||||
msg_data: *const u8,
|
||||
msg_len: u32,
|
||||
sig_data: *const u8,
|
||||
pubkey_data: *const u8
|
||||
pubkey_data: *const u8,
|
||||
) -> u32;
|
||||
|
||||
/// Generate an `sr25519` key pair for the given key type id and store the public
|
||||
/// key in `out`.
|
||||
fn ext_sr25519_generate(id: *const u8, seed: *const u8, seed_len: u32, out: *mut u8);
|
||||
|
||||
/// Sign the given `msg` with the `sr25519` key pair that corresponds to then given key
|
||||
/// type id and public key. The raw signature is stored in `out`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `0` on success
|
||||
/// - nonezero if something failed, e.g. retrieving of the key.
|
||||
fn ext_sr25519_sign(
|
||||
id: *const u8,
|
||||
pubkey: *const u8,
|
||||
msg: *const u8,
|
||||
msg_len: u32,
|
||||
out: *mut 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
|
||||
pubkey_data: *mut u8,
|
||||
) -> u32;
|
||||
|
||||
//================================
|
||||
@@ -398,94 +446,6 @@ pub mod ext {
|
||||
/// runtime code can always rely on it.
|
||||
fn ext_network_state(written_out: *mut u32) -> *mut u8;
|
||||
|
||||
/// Returns the locally configured authority public key, if available.
|
||||
/// The `crypto` argument is `offchain::CryptoKind` converted to `u32`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The encoded `Result<PublicKey encoded to Vec<u8>, ()>`.
|
||||
/// `written_out` contains the length of the message.
|
||||
///
|
||||
/// The ownership of the returned buffer is transferred to the runtime
|
||||
/// code and the runtime is responsible for freeing it. This is always
|
||||
/// a properly allocated pointer (which cannot be NULL), hence the
|
||||
/// runtime code can always rely on it.
|
||||
fn ext_pubkey(key: u64, written_out: *mut u32) -> *mut u8;
|
||||
|
||||
/// Create new key(pair) for signing/encryption/decryption.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - A crypto key id (if the value is less than u16::max_value)
|
||||
/// - `u32::max_value` in case the crypto is not supported
|
||||
fn ext_new_crypto_key(crypto: u32) -> u64;
|
||||
|
||||
/// Encrypt a piece of data using given crypto key.
|
||||
///
|
||||
/// If `key` is `0`, it will attempt to use current authority key of given `kind`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `0` in case the key is invalid, `msg_len` is set to `u32::max_value`
|
||||
/// - Otherwise, pointer to the encrypted message in memory,
|
||||
/// `msg_len` contains the length of the message.
|
||||
fn ext_encrypt(
|
||||
key: u64,
|
||||
data: *const u8,
|
||||
data_len: u32,
|
||||
msg_len: *mut u32
|
||||
) -> *mut u8;
|
||||
|
||||
/// Decrypt a piece of data using given crypto key.
|
||||
///
|
||||
/// If `key` is `0`, it will attempt to use current authority key of given `kind`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `0` in case the key is invalid or data couldn't be decrypted,
|
||||
/// `msg_len` is set to `u32::max_value`
|
||||
/// - Otherwise, pointer to the decrypted message in memory,
|
||||
/// `msg_len` contains the length of the message.
|
||||
fn ext_decrypt(
|
||||
key: u64,
|
||||
data: *const u8,
|
||||
data_len: u32,
|
||||
msg_len: *mut u32
|
||||
) -> *mut u8;
|
||||
|
||||
/// Sign a piece of data using given crypto key.
|
||||
///
|
||||
/// If `key` is `0`, it will attempt to use current authority key of given `kind`.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - `0` in case the key is invalid,
|
||||
/// `sig_data_len` is set to `u32::max_value`
|
||||
/// - Otherwise, pointer to the signature in memory,
|
||||
/// `sig_data_len` contains the length of the signature.
|
||||
fn ext_sign(
|
||||
key: u64,
|
||||
data: *const u8,
|
||||
data_len: u32,
|
||||
sig_data_len: *mut u32
|
||||
) -> *mut u8;
|
||||
|
||||
/// Verifies that `signature` for `msg` matches given `key`.
|
||||
///
|
||||
/// If `key` is `0`, it will attempt to use current authority key of given `kind`.
|
||||
///
|
||||
/// # Returns
|
||||
/// - `0` in case the signature is correct
|
||||
/// - `1` in case it doesn't match the key
|
||||
/// - `u32::max_value` if the key is invalid.
|
||||
fn ext_verify(
|
||||
key: u64,
|
||||
msg: *const u8,
|
||||
msg_len: u32,
|
||||
signature: *const u8,
|
||||
signature_len: u32
|
||||
) -> u32;
|
||||
|
||||
/// Returns current UNIX timestamp (milliseconds)
|
||||
fn ext_timestamp() -> u64;
|
||||
|
||||
@@ -871,15 +831,105 @@ impl HashingApi for () {
|
||||
}
|
||||
|
||||
impl CryptoApi for () {
|
||||
fn ed25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
|
||||
fn ed25519_public_keys(id: KeyTypeId) -> Vec<ed25519::Public> {
|
||||
let mut res_len = 0u32;
|
||||
unsafe {
|
||||
ext_ed25519_verify.get()(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0
|
||||
let res_ptr = ext_ed25519_public_keys.get()(id.0.as_ptr(), &mut res_len);
|
||||
Vec::decode(&mut rstd::slice::from_raw_parts(res_ptr, res_len as usize)).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
fn sr25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool {
|
||||
fn ed25519_generate(id: KeyTypeId, seed: Option<&str>) -> ed25519::Public {
|
||||
let mut res = [0u8; 32];
|
||||
let seed = seed.as_ref().map(|s| s.as_bytes()).unwrap_or(&[]);
|
||||
unsafe {
|
||||
ext_sr25519_verify.get()(msg.as_ptr(), msg.len() as u32, sig.as_ptr(), pubkey.as_ref().as_ptr()) == 0
|
||||
ext_ed25519_generate.get()(id.0.as_ptr(), seed.as_ptr(), seed.len() as u32, res.as_mut_ptr())
|
||||
};
|
||||
ed25519::Public(res)
|
||||
}
|
||||
|
||||
fn ed25519_sign<M: AsRef<[u8]>>(
|
||||
id: KeyTypeId,
|
||||
pubkey: &ed25519::Public,
|
||||
msg: &M,
|
||||
) -> Option<ed25519::Signature> {
|
||||
let mut res = [0u8; 64];
|
||||
let success = unsafe {
|
||||
ext_ed25519_sign.get()(
|
||||
id.0.as_ptr(),
|
||||
pubkey.0.as_ptr(),
|
||||
msg.as_ref().as_ptr(),
|
||||
msg.as_ref().len() as u32,
|
||||
res.as_mut_ptr(),
|
||||
) == 0
|
||||
};
|
||||
|
||||
if success {
|
||||
Some(ed25519::Signature(res))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pubkey: &ed25519::Public) -> bool {
|
||||
unsafe {
|
||||
ext_ed25519_verify.get()(
|
||||
msg.as_ptr(),
|
||||
msg.len() as u32,
|
||||
sig.0.as_ptr(),
|
||||
pubkey.0.as_ptr(),
|
||||
) == 0
|
||||
}
|
||||
}
|
||||
|
||||
fn sr25519_public_keys(id: KeyTypeId) -> Vec<sr25519::Public> {
|
||||
let mut res_len = 0u32;
|
||||
unsafe {
|
||||
let res_ptr = ext_sr25519_public_keys.get()(id.0.as_ptr(), &mut res_len);
|
||||
Vec::decode(&mut rstd::slice::from_raw_parts(res_ptr, res_len as usize)).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
fn sr25519_generate(id: KeyTypeId, seed: Option<&str>) -> sr25519::Public {
|
||||
let mut res = [0u8;32];
|
||||
let seed = seed.as_ref().map(|s| s.as_bytes()).unwrap_or(&[]);
|
||||
unsafe {
|
||||
ext_sr25519_generate.get()(id.0.as_ptr(), seed.as_ptr(), seed.len() as u32, res.as_mut_ptr())
|
||||
};
|
||||
sr25519::Public(res)
|
||||
}
|
||||
|
||||
fn sr25519_sign<M: AsRef<[u8]>>(
|
||||
id: KeyTypeId,
|
||||
pubkey: &sr25519::Public,
|
||||
msg: &M,
|
||||
) -> Option<sr25519::Signature> {
|
||||
let mut res = [0u8; 64];
|
||||
let success = unsafe {
|
||||
ext_sr25519_sign.get()(
|
||||
id.0.as_ptr(),
|
||||
pubkey.0.as_ptr(),
|
||||
msg.as_ref().as_ptr(),
|
||||
msg.as_ref().len() as u32,
|
||||
res.as_mut_ptr(),
|
||||
) == 0
|
||||
};
|
||||
|
||||
if success {
|
||||
Some(sr25519::Signature(res))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pubkey: &sr25519::Public) -> bool {
|
||||
unsafe {
|
||||
ext_sr25519_verify.get()(
|
||||
msg.as_ptr(),
|
||||
msg.len() as u32,
|
||||
sig.0.as_ptr(),
|
||||
pubkey.0.as_ptr(),
|
||||
) == 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -925,104 +975,6 @@ impl OffchainApi for () {
|
||||
}
|
||||
}
|
||||
|
||||
fn pubkey(key: CryptoKey) -> Result<Vec<u8>, ()> {
|
||||
let mut len = 0u32;
|
||||
let raw_result = unsafe {
|
||||
let ptr = ext_pubkey.get()(
|
||||
key.into(),
|
||||
&mut len,
|
||||
);
|
||||
|
||||
from_raw_parts(ptr, len)
|
||||
};
|
||||
|
||||
match raw_result {
|
||||
Some(raw_result) => codec::Decode::decode(&mut &*raw_result).unwrap_or(Err(())),
|
||||
None => Err(())
|
||||
}
|
||||
}
|
||||
|
||||
fn new_crypto_key(crypto: offchain::CryptoKind) -> Result<offchain::CryptoKey, ()> {
|
||||
let crypto = crypto.into();
|
||||
let ret = unsafe {
|
||||
ext_new_crypto_key.get()(crypto)
|
||||
};
|
||||
offchain::CryptoKey::try_from(ret)
|
||||
}
|
||||
|
||||
fn encrypt(
|
||||
key: offchain::CryptoKey,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
let mut len = 0_u32;
|
||||
unsafe {
|
||||
let ptr = ext_encrypt.get()(
|
||||
key.into(),
|
||||
data.as_ptr(),
|
||||
data.len() as u32,
|
||||
&mut len
|
||||
);
|
||||
|
||||
from_raw_parts(ptr, len).ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
fn decrypt(
|
||||
key: offchain::CryptoKey,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
let mut len = 0_u32;
|
||||
unsafe {
|
||||
let ptr = ext_decrypt.get()(
|
||||
key.into(),
|
||||
data.as_ptr(),
|
||||
data.len() as u32,
|
||||
&mut len
|
||||
);
|
||||
|
||||
from_raw_parts(ptr, len).ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
fn sign(
|
||||
key: offchain::CryptoKey,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
let mut len = 0_u32;
|
||||
unsafe {
|
||||
let ptr = ext_sign.get()(
|
||||
key.into(),
|
||||
data.as_ptr(),
|
||||
data.len() as u32,
|
||||
&mut len
|
||||
);
|
||||
|
||||
from_raw_parts(ptr, len).ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
fn verify(
|
||||
key: offchain::CryptoKey,
|
||||
msg: &[u8],
|
||||
signature: &[u8],
|
||||
) -> Result<bool, ()> {
|
||||
let val = unsafe {
|
||||
ext_verify.get()(
|
||||
key.into(),
|
||||
msg.as_ptr(),
|
||||
msg.len() as u32,
|
||||
signature.as_ptr(),
|
||||
signature.len() as u32,
|
||||
)
|
||||
};
|
||||
|
||||
match val {
|
||||
0 => Ok(true),
|
||||
1 => Ok(false),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn timestamp() -> offchain::Timestamp {
|
||||
offchain::Timestamp::from_unix_millis(unsafe {
|
||||
ext_timestamp.get()()
|
||||
|
||||
Reference in New Issue
Block a user