Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Add keypair function to trait
Browse files Browse the repository at this point in the history
  • Loading branch information
sorpaas committed Nov 5, 2020
1 parent 064d31d commit ad921b0
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 34 deletions.
109 changes: 75 additions & 34 deletions client/keystore/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use sp_keystore::{
SyncCryptoStore,
vrf::{VRFTranscriptData, VRFSignature, make_transcript},
};
use sp_application_crypto::{ed25519, sr25519, ecdsa, AppPair, AppKey, IsWrappedBy};
use sp_application_crypto::{ed25519, sr25519, ecdsa};

use crate::{Result, Error};

Expand All @@ -57,14 +57,6 @@ impl LocalKeystore {
let inner = KeystoreInner::new_in_memory();
Self(RwLock::new(inner))
}

/// Get a key pair for the given public key.
///
/// This function is only available for a local keystore. If your application plans to work with
/// remote keystores, you do not want to depend on it.
pub fn key_pair<Pair: AppPair>(&self, public: &<Pair as AppKey>::Public) -> Result<Pair> {
self.0.read().key_pair::<Pair>(public)
}
}

#[async_trait]
Expand All @@ -77,6 +69,14 @@ impl CryptoStore for LocalKeystore {
SyncCryptoStore::sr25519_public_keys(self, id)
}

async fn sr25519_key_pair(
&self,
id: KeyTypeId,
public: &sr25519::Public,
) -> std::result::Result<sr25519::Pair, TraitError> {
SyncCryptoStore::sr25519_key_pair(self, id, public)
}

async fn sr25519_generate_new(
&self,
id: KeyTypeId,
Expand All @@ -89,6 +89,14 @@ impl CryptoStore for LocalKeystore {
SyncCryptoStore::ed25519_public_keys(self, id)
}

async fn ed25519_key_pair(
&self,
id: KeyTypeId,
public: &ed25519::Public,
) -> std::result::Result<ed25519::Pair, TraitError> {
SyncCryptoStore::ed25519_key_pair(self, id, public)
}

async fn ed25519_generate_new(
&self,
id: KeyTypeId,
Expand All @@ -101,6 +109,14 @@ impl CryptoStore for LocalKeystore {
SyncCryptoStore::ecdsa_public_keys(self, id)
}

async fn ecdsa_key_pair(
&self,
id: KeyTypeId,
public: &ecdsa::Public,
) -> std::result::Result<ecdsa::Pair, TraitError> {
SyncCryptoStore::ecdsa_key_pair(self, id, public)
}

async fn ecdsa_generate_new(
&self,
id: KeyTypeId,
Expand Down Expand Up @@ -182,21 +198,21 @@ impl SyncCryptoStore for LocalKeystore {
ed25519::CRYPTO_ID => {
let pub_key = ed25519::Public::from_slice(key.1.as_slice());
let key_pair: ed25519::Pair = self.0.read()
.key_pair_by_type::<ed25519::Pair>(&pub_key, id)
.key_pair_by_type::<ed25519::Pair>(id, &pub_key)
.map_err(|e| TraitError::from(e))?;
Ok(key_pair.sign(msg).encode())
}
sr25519::CRYPTO_ID => {
let pub_key = sr25519::Public::from_slice(key.1.as_slice());
let key_pair: sr25519::Pair = self.0.read()
.key_pair_by_type::<sr25519::Pair>(&pub_key, id)
.key_pair_by_type::<sr25519::Pair>(id, &pub_key)
.map_err(|e| TraitError::from(e))?;
Ok(key_pair.sign(msg).encode())
},
ecdsa::CRYPTO_ID => {
let pub_key = ecdsa::Public::from_slice(key.1.as_slice());
let key_pair: ecdsa::Pair = self.0.read()
.key_pair_by_type::<ecdsa::Pair>(&pub_key, id)
.key_pair_by_type::<ecdsa::Pair>(id, &pub_key)
.map_err(|e| TraitError::from(e))?;
Ok(key_pair.sign(msg).encode())
}
Expand All @@ -214,13 +230,21 @@ impl SyncCryptoStore for LocalKeystore {
.unwrap_or_default()
}

fn sr25519_key_pair(
&self,
id: KeyTypeId,
public: &sr25519::Public,
) -> std::result::Result<sr25519::Pair, TraitError> {
Ok(self.0.read().key_pair_by_type::<sr25519::Pair>(id, public)?)
}

fn sr25519_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> std::result::Result<sr25519::Public, TraitError> {
let pair = match seed {
Some(seed) => self.0.write().insert_ephemeral_from_seed_by_type::<sr25519::Pair>(seed, id),
Some(seed) => self.0.write().insert_ephemeral_from_seed_by_type::<sr25519::Pair>(id, seed),
None => self.0.write().generate_by_type::<sr25519::Pair>(id),
}.map_err(|e| -> TraitError { e.into() })?;

Expand All @@ -237,13 +261,21 @@ impl SyncCryptoStore for LocalKeystore {
.unwrap_or_default()
}

fn ed25519_key_pair(
&self,
id: KeyTypeId,
public: &ed25519::Public,
) -> std::result::Result<ed25519::Pair, TraitError> {
Ok(self.0.read().key_pair_by_type::<ed25519::Pair>(id, public)?)
}

fn ed25519_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> std::result::Result<ed25519::Public, TraitError> {
let pair = match seed {
Some(seed) => self.0.write().insert_ephemeral_from_seed_by_type::<ed25519::Pair>(seed, id),
Some(seed) => self.0.write().insert_ephemeral_from_seed_by_type::<ed25519::Pair>(id, seed),
None => self.0.write().generate_by_type::<ed25519::Pair>(id),
}.map_err(|e| -> TraitError { e.into() })?;

Expand All @@ -260,13 +292,21 @@ impl SyncCryptoStore for LocalKeystore {
.unwrap_or_default()
}

fn ecdsa_key_pair(
&self,
id: KeyTypeId,
public: &ecdsa::Public,
) -> std::result::Result<ecdsa::Pair, TraitError> {
Ok(self.0.read().key_pair_by_type::<ecdsa::Pair>(id, public)?)
}

fn ecdsa_generate_new(
&self,
id: KeyTypeId,
seed: Option<&str>,
) -> std::result::Result<ecdsa::Public, TraitError> {
let pair = match seed {
Some(seed) => self.0.write().insert_ephemeral_from_seed_by_type::<ecdsa::Pair>(seed, id),
Some(seed) => self.0.write().insert_ephemeral_from_seed_by_type::<ecdsa::Pair>(id, seed),
None => self.0.write().generate_by_type::<ecdsa::Pair>(id),
}.map_err(|e| -> TraitError { e.into() })?;

Expand All @@ -280,7 +320,7 @@ impl SyncCryptoStore for LocalKeystore {
}

fn has_keys(&self, public_keys: &[(Vec<u8>, KeyTypeId)]) -> bool {
public_keys.iter().all(|(p, t)| self.0.read().key_phrase_by_type(&p, *t).is_ok())
public_keys.iter().all(|(p, t)| self.0.read().key_phrase_by_type(*t, &p).is_ok())
}

fn sr25519_vrf_sign(
Expand All @@ -290,7 +330,7 @@ impl SyncCryptoStore for LocalKeystore {
transcript_data: VRFTranscriptData,
) -> std::result::Result<VRFSignature, TraitError> {
let transcript = make_transcript(transcript_data);
let pair = self.0.read().key_pair_by_type::<Sr25519Pair>(public, key_type)
let pair = self.0.read().key_pair_by_type::<Sr25519Pair>(key_type, public)
.map_err(|e| TraitError::PairNotFound(e.to_string()))?;

let (inout, proof, _) = pair.as_ref().vrf_sign(transcript);
Expand Down Expand Up @@ -356,8 +396,8 @@ impl KeystoreInner {
/// Get the key phrase for the given public key and key type from the in-memory store.
fn get_additional_pair(
&self,
public: &[u8],
key_type: KeyTypeId,
public: &[u8],
) -> Option<&String> {
let key = (key_type, public.to_vec());
self.additional.get(&key)
Expand All @@ -366,7 +406,7 @@ impl KeystoreInner {
/// Insert the given public/private key pair with the given key type.
///
/// Does not place it into the file system store.
fn insert_ephemeral_pair<Pair: PairT>(&mut self, pair: &Pair, seed: &str, key_type: KeyTypeId) {
fn insert_ephemeral_pair<Pair: PairT>(&mut self, key_type: KeyTypeId, pair: &Pair, seed: &str) {
let key = (key_type, pair.public().to_raw_vec());
self.additional.insert(key, seed.into());
}
Expand Down Expand Up @@ -401,17 +441,17 @@ impl KeystoreInner {
/// Does not place it into the file system store.
pub fn insert_ephemeral_from_seed_by_type<Pair: PairT>(
&mut self,
seed: &str,
key_type: KeyTypeId,
seed: &str,
) -> Result<Pair> {
let pair = Pair::from_string(seed, None).map_err(|_| Error::InvalidSeed)?;
self.insert_ephemeral_pair(&pair, seed, key_type);
self.insert_ephemeral_pair(key_type, &pair, seed);
Ok(pair)
}

/// Get the key phrase for a given public key and key type.
fn key_phrase_by_type(&self, public: &[u8], key_type: KeyTypeId) -> Result<String> {
if let Some(phrase) = self.get_additional_pair(public, key_type) {
fn key_phrase_by_type(&self, key_type: KeyTypeId, public: &[u8]) -> Result<String> {
if let Some(phrase) = self.get_additional_pair(key_type, public) {
return Ok(phrase.clone())
}

Expand All @@ -422,11 +462,12 @@ impl KeystoreInner {
}

/// Get a key pair for the given public key and key type.
pub fn key_pair_by_type<Pair: PairT>(&self,
public: &Pair::Public,
pub fn key_pair_by_type<Pair: PairT>(
&self,
key_type: KeyTypeId,
public: &Pair::Public,
) -> Result<Pair> {
let phrase = self.key_phrase_by_type(public.as_slice(), key_type)?;
let phrase = self.key_phrase_by_type(key_type, public.as_slice())?;
let pair = Pair::from_string(
&phrase,
self.password(),
Expand Down Expand Up @@ -478,11 +519,6 @@ impl KeystoreInner {

Ok(public_keys)
}

/// Get a key pair for the given public key.
pub fn key_pair<Pair: AppPair>(&self, public: &<Pair as AppKey>::Public) -> Result<Pair> {
self.key_pair_by_type::<Pair::Generic>(IsWrappedBy::from_ref(public), Pair::ID).map(Into::into)
}
}


Expand All @@ -495,15 +531,15 @@ mod tests {
crypto::Ss58Codec,
testing::SR25519,
};
use sp_application_crypto::{ed25519, sr25519, AppPublic};
use sp_application_crypto::{ed25519, sr25519, AppPublic, AppPair, AppKey, IsWrappedBy};
use std::{
fs,
str::FromStr,
};

impl KeystoreInner {
fn insert_ephemeral_from_seed<Pair: AppPair>(&mut self, seed: &str) -> Result<Pair> {
self.insert_ephemeral_from_seed_by_type::<Pair::Generic>(seed, Pair::ID).map(Into::into)
self.insert_ephemeral_from_seed_by_type::<Pair::Generic>(Pair::ID, seed).map(Into::into)
}

fn public_keys<Public: AppPublic>(&self) -> Result<Vec<Public>> {
Expand All @@ -518,6 +554,11 @@ mod tests {
fn generate<Pair: AppPair>(&self) -> Result<Pair> {
self.generate_by_type::<Pair::Generic>(Pair::ID).map(Into::into)
}

/// Get a key pair for the given public key.
fn key_pair<Pair: AppPair>(&self, public: &<Pair as AppKey>::Public) -> Result<Pair> {
self.key_pair_by_type::<Pair::Generic>(Pair::ID, IsWrappedBy::from_ref(public)).map(Into::into)
}
}

#[test]
Expand Down Expand Up @@ -621,8 +662,8 @@ mod tests {
).expect("Inserts unknown key");

let store_key_pair = store.key_pair_by_type::<sr25519::AppPair>(
&key_pair.public(),
SR25519,
&key_pair.public(),
).expect("Gets key pair from keystore");

assert_eq!(key_pair.public(), store_key_pair.public());
Expand Down
51 changes: 51 additions & 0 deletions primitives/keystore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ pub enum Error {
pub trait CryptoStore: Send + Sync {
/// Returns all sr25519 public keys for the given key type.
async fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public>;
/// Returns an sr25519 key pair given the public key, if available.
///
/// Note that if a key is available in the keystore, its private key may still not be retrivable.
async fn sr25519_key_pair(
&self,
id: KeyTypeId,
public: &sr25519::Public,
) -> Result<sr25519::Pair, Error>;
/// Generate a new sr25519 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.
Expand All @@ -65,6 +73,14 @@ pub trait CryptoStore: Send + Sync {
) -> Result<sr25519::Public, Error>;
/// Returns all ed25519 public keys for the given key type.
async fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public>;
/// Returns an ed25519 key pair given the public key, if available.
///
/// Note that if a key is available in the keystore, its private key may still not be retrivable.
async fn ed25519_key_pair(
&self,
id: KeyTypeId,
public: &ed25519::Public,
) -> Result<ed25519::Pair, Error>;
/// Generate a new ed25519 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.
Expand All @@ -77,6 +93,14 @@ pub trait CryptoStore: Send + Sync {
) -> Result<ed25519::Public, Error>;
/// Returns all ecdsa public keys for the given key type.
async fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public>;
/// Returns an ecdsa key pair given the public key, if available.
///
/// Note that if a key is available in the keystore, its private key may still not be retrivable.
async fn ecdsa_key_pair(
&self,
id: KeyTypeId,
public: &ecdsa::Public,
) -> Result<ecdsa::Pair, Error>;
/// 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.
Expand Down Expand Up @@ -211,6 +235,15 @@ pub trait SyncCryptoStore: CryptoStore + Send + Sync {
/// Returns all sr25519 public keys for the given key type.
fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public>;

/// Returns an sr25519 key pair given the public key, if available.
///
/// Note that if a key is available in the keystore, its private key may still not be retrivable.
fn sr25519_key_pair(
&self,
id: KeyTypeId,
public: &sr25519::Public,
) -> Result<sr25519::Pair, Error>;

/// Generate a new sr25519 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.
Expand All @@ -225,6 +258,15 @@ pub trait SyncCryptoStore: CryptoStore + Send + Sync {
/// Returns all ed25519 public keys for the given key type.
fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public>;

/// Returns an ed25519 key pair given the public key, if available.
///
/// Note that if a key is available in the keystore, its private key may still not be retrivable.
fn ed25519_key_pair(
&self,
id: KeyTypeId,
public: &ed25519::Public,
) -> Result<ed25519::Pair, Error>;

/// Generate a new ed25519 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.
Expand All @@ -239,6 +281,15 @@ pub trait SyncCryptoStore: CryptoStore + Send + Sync {
/// Returns all ecdsa public keys for the given key type.
fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public>;

/// Returns an ecdsa key pair given the public key, if available.
///
/// Note that if a key is available in the keystore, its private key may still not be retrivable.
fn ecdsa_key_pair(
&self,
id: KeyTypeId,
public: &ecdsa::Public,
) -> Result<ecdsa::Pair, Error>;

/// 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.
Expand Down
Loading

0 comments on commit ad921b0

Please sign in to comment.