Added RuntimePublic for ecdsa public key. (#6029)

* add generate ecdsa, etc to keystore

* impl ecdsa needed traits

* add ecdsa to sr_io

* add ecdsa to application-crypto

* add ecdsa to test-utils

* add ecdsa debug derive

* fix ecdsa public
This commit is contained in:
satellitex
2020-05-16 00:04:38 +09:00
committed by GitHub
parent f36f57b0bf
commit 302c543b49
11 changed files with 364 additions and 14 deletions
+30 -7
View File
@@ -38,6 +38,7 @@ use crate::crypto::Ss58Codec;
#[cfg(feature = "std")]
use serde::{de, Serializer, Serialize, Deserializer, Deserialize};
use crate::crypto::{Public as TraitPublic, CryptoTypePublicPair, UncheckedFrom, CryptoType, Derive, CryptoTypeId};
use sp_runtime_interface::pass_by::PassByInner;
#[cfg(feature = "full_crypto")]
use secp256k1::{PublicKey, SecretKey};
@@ -51,7 +52,7 @@ pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds");
type Seed = [u8; 32];
/// The ECDSA compressed public key.
#[derive(Clone, Encode, Decode)]
#[derive(Clone, Encode, Decode, PassByInner)]
pub struct Public([u8; 33]);
impl PartialOrd for Public {
@@ -125,6 +126,18 @@ impl TraitPublic for Public {
}
}
impl From<Public> for CryptoTypePublicPair {
fn from(key: Public) -> Self {
(&key).into()
}
}
impl From<&Public> for CryptoTypePublicPair {
fn from(key: &Public) -> Self {
CryptoTypePublicPair(CRYPTO_ID, key.to_raw_vec())
}
}
impl Derive for Public {}
impl Default for Public {
@@ -178,12 +191,17 @@ impl std::fmt::Display for Public {
}
}
#[cfg(feature = "std")]
impl std::fmt::Debug for Public {
impl sp_std::fmt::Debug for Public {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let s = self.to_ss58check();
write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.as_ref()), &s[0..8])
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
#[cfg(feature = "std")]
@@ -209,7 +227,7 @@ impl sp_std::hash::Hash for Public {
}
/// A signature (a 512-bit value, plus 8 bits for recovery ID).
#[derive(Encode, Decode)]
#[derive(Encode, Decode, PassByInner)]
pub struct Signature([u8; 65]);
impl sp_std::convert::TryFrom<&[u8]> for Signature {
@@ -289,11 +307,16 @@ impl AsMut<[u8]> for Signature {
}
}
#[cfg(feature = "std")]
impl std::fmt::Debug for Signature {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
impl sp_std::fmt::Debug for Signature {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0))
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
#[cfg(feature = "full_crypto")]
+49 -1
View File
@@ -21,7 +21,7 @@ use crate::crypto::KeyTypeId;
#[cfg(feature = "std")]
use crate::{
crypto::{Pair, Public, CryptoTypePublicPair},
ed25519, sr25519,
ed25519, sr25519, ecdsa,
traits::BareCryptoStoreError
};
#[cfg(feature = "std")]
@@ -30,6 +30,8 @@ use std::collections::HashSet;
pub const ED25519: KeyTypeId = KeyTypeId(*b"ed25");
/// Key type for generic Sr 25519 key.
pub const SR25519: KeyTypeId = KeyTypeId(*b"sr25");
/// Key type for generic Sr 25519 key.
pub const ECDSA: KeyTypeId = KeyTypeId(*b"ecds");
/// A keystore implementation usable in tests.
#[cfg(feature = "std")]
@@ -62,6 +64,14 @@ impl KeyStore {
)
}
fn ecdsa_key_pair(&self, id: KeyTypeId, pub_key: &ecdsa::Public) -> Option<ecdsa::Pair> {
self.keys.get(&id)
.and_then(|inner|
inner.get(pub_key.as_slice())
.map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid"))
)
}
}
#[cfg(feature = "std")]
@@ -74,6 +84,7 @@ impl crate::traits::BareCryptoStore for KeyStore {
.fold(Vec::new(), |mut v, k| {
v.push(CryptoTypePublicPair(sr25519::CRYPTO_ID, k.clone()));
v.push(CryptoTypePublicPair(ed25519::CRYPTO_ID, k.clone()));
v.push(CryptoTypePublicPair(ecdsa::CRYPTO_ID, k.clone()));
v
}))
})
@@ -142,6 +153,37 @@ impl crate::traits::BareCryptoStore for KeyStore {
}
}
fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public> {
self.keys.get(&id)
.map(|keys|
keys.values()
.map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid"))
.map(|p| p.public())
.collect()
)
.unwrap_or_default()
}
fn ecdsa_generate_new(
&mut self,
id: KeyTypeId,
seed: Option<&str>,
) -> Result<ecdsa::Public, BareCryptoStoreError> {
match seed {
Some(seed) => {
let pair = ecdsa::Pair::from_string(seed, None)
.map_err(|_| BareCryptoStoreError::ValidationError("Generates an `ecdsa` pair.".to_owned()))?;
self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into());
Ok(pair.public())
},
None => {
let (pair, phrase, _) = ecdsa::Pair::generate_with_phrase(None);
self.keys.entry(id).or_default().insert(pair.public().to_raw_vec(), phrase);
Ok(pair.public())
}
}
}
fn insert_unknown(&mut self, id: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> {
self.keys.entry(id).or_default().insert(public.to_owned(), suri.to_string());
Ok(())
@@ -187,6 +229,12 @@ impl crate::traits::BareCryptoStore for KeyStore {
.ok_or(BareCryptoStoreError::PairNotFound("sr25519".to_owned()))?;
return Ok(key_pair.sign(msg).encode());
}
ecdsa::CRYPTO_ID => {
let key_pair: ecdsa::Pair = self
.ecdsa_key_pair(id, &ecdsa::Public::from_slice(key.1.as_slice()))
.ok_or(BareCryptoStoreError::PairNotFound("ecdsa".to_owned()))?;
return Ok(key_pair.sign(msg).encode());
}
_ => Err(BareCryptoStoreError::KeyNotSupported(id))
}
}
+13 -1
View File
@@ -19,7 +19,7 @@
use crate::{
crypto::{KeyTypeId, CryptoTypePublicPair},
ed25519, sr25519,
ed25519, sr25519, ecdsa,
};
use std::{
@@ -77,6 +77,18 @@ pub trait BareCryptoStore: Send + Sync {
id: KeyTypeId,
seed: Option<&str>,
) -> Result<ed25519::Public, BareCryptoStoreError>;
/// Returns all ecdsa public keys for the given key type.
fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public>;
/// Generate a new ecdsa key pair for the given key type and an optional seed.
///
/// If the given seed is `Some(_)`, the key pair will only be stored in memory.
///
/// Returns the public key of the generated key pair.
fn ecdsa_generate_new(
&mut self,
id: KeyTypeId,
seed: Option<&str>,
) -> Result<ecdsa::Public, BareCryptoStoreError>;
/// Insert a new key. This doesn't require any known of the crypto; but a public key must be
/// manually provided.