tpfs_krypt 7.1.8

An interface for accessing secrets
Documentation
//! The In Memory Key Manager Module which should contain the config and struct for
//! working with a key manager that is only intended to work in situations where
//! the keys are to not be persisted. Please take care to not use this in a
//! production running application.
//!
//! # Examples
//!
//! Creating a KeyManager from config, import keys then sign a message with it.
//!
//! ```
//! use sp_core::{
//!     crypto::{Pair, Ss58Codec, DEV_PHRASE},
//!     sr25519,
//! };
//! use tpfs_krypt::{
//!     config::{KeyManagerConfig, KryptConfig},
//!     errors::KeyManagementError,
//!     from_config, KeyIdentifier, InMemoryKeyManagerConfig, KeyManagement, KeyType,
//! };
//!
//! fn create_key_manager() -> Result<Box<dyn KeyManagement>, KeyManagementError> {
//!     let config = KryptConfig {
//!         key_manager_config: KeyManagerConfig::InMemoryKeyManager(InMemoryKeyManagerConfig {
//!             initial_keys: vec![(KeyType::SubstrateSr25519, format!("{}//Demo", DEV_PHRASE))],
//!         }),
//!     };
//!
//!     from_config(config)
//! }
//!
//! fn main() -> Result<(), KeyManagementError> {
//!     let key_manager = create_key_manager()?;
//!     let pair = sr25519::Pair::from_string("//Demo", None)?;
//!     let address = KeyIdentifier {
//!         value: pair.public().to_ss58check(),
//!         key_type: KeyType::SubstrateSr25519,
//!     };
//!     assert!(key_manager.has_key(&address)?);
//!     let signature = key_manager.sign(&address, b"A Message")?;
//!     println!("Signature as hex: {:x?}", signature.as_ref().as_ref());
//!     Ok(())
//! }
//! ```

#[cfg(test)]
mod unit_tests;

use crate::{
    config::ConfigValidation,
    core::{KeyPair, KeyStorage},
    crypto::translator::KeyPairInstance,
    errors::{KeyManagementError, Result},
    KeyIdentifier, KeyType, NewKeyId,
};
use secrecy::Secret;
use std::collections::HashMap;

/// The configuration used to create an In Memory KeyManager. This key manager
/// will create a hash table in the process to retrieve and store key pairs from.
///
/// **NOTE**: When the process dies so does what this key manager stores. This is intended for
/// tests or utilities and not intended for long running processes where persisting
/// each generated keypair is vital.
///
/// # Examples
///
/// Create a config for an initially empty In Memory KeyManager
///
/// ```
/// use tpfs_krypt::{
///     config::{KeyManagerConfig, KryptConfig},
///     InMemoryKeyManagerConfig
/// };
///
/// let config = KryptConfig {
///     key_manager_config: KeyManagerConfig::InMemoryKeyManager(InMemoryKeyManagerConfig {
///         initial_keys: vec![],
///     }),
/// };
/// ```
///
/// Create a config with a couple of initial keys.
///
/// ```
/// use sp_core::crypto::DEV_PHRASE;
/// use tpfs_krypt::{
///     config::{KeyManagerConfig, KryptConfig},
///     InMemoryKeyManagerConfig, KeyType
/// };
///
/// let config = KryptConfig {
///     key_manager_config: KeyManagerConfig::InMemoryKeyManager(InMemoryKeyManagerConfig {
///         initial_keys: vec![
///             (KeyType::SubstrateSr25519, format!("{}//Demo1", DEV_PHRASE)),
///             (KeyType::SubstrateSr25519, format!("{}//Demo2", DEV_PHRASE)),
///             (KeyType::SubstrateEd25519, format!("{}//Demo3", DEV_PHRASE)),
///         ],
///     }),
/// };
/// ```
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct InMemoryKeyManagerConfig {
    /// The initial keys that should be included in the In Memory KeyManager.
    /// This is merely a convenience for testing scenarios and can include an empty
    /// vec.
    pub initial_keys: Vec<(KeyType, String)>,
}

impl ConfigValidation for InMemoryKeyManagerConfig {
    fn validate(&self) -> Result<()> {
        for (key_type, secret) in &self.initial_keys {
            KeyPairInstance::from_secret(Secret::new(secret.clone()), *key_type)?;
        }

        Ok(())
    }
}

/// The In Memory Key Manager struct which can be used to initialize a series of
/// keys and import the data.
pub(crate) struct InMemoryKeyManager {
    pub(crate) keypairs: HashMap<KeyIdentifier, KeyPairInstance>,
}

impl InMemoryKeyManager {
    pub(crate) fn new(config: InMemoryKeyManagerConfig) -> Self {
        let keypairs: HashMap<KeyIdentifier, KeyPairInstance> = config
            .initial_keys
            .into_iter()
            .map(|(key_type, secret)| {
                let translator =
                    KeyPairInstance::from_secret(Secret::new(secret), key_type).unwrap();
                let address = translator.identifier();

                (address, translator)
            })
            .collect();

        InMemoryKeyManager { keypairs }
    }
}

impl KeyStorage for InMemoryKeyManager {
    fn store_has_key(&self, id: &KeyIdentifier) -> Result<bool> {
        Ok(self.keypairs.contains_key(id))
    }

    fn get_key(&self, id: &KeyIdentifier) -> Result<KeyPairInstance> {
        let key_pair = self
            .keypairs
            .get(id)
            .ok_or(KeyManagementError::AddressNotFound {
                address: id.value.clone(),
            })?;

        let secret = key_pair.to_secret()?;
        let key_type = key_pair.get_key_type();
        KeyPairInstance::from_secret(secret, key_type)
    }

    fn get_keys(&self) -> Result<Vec<KeyIdentifier>> {
        Ok(self.keypairs.keys().cloned().collect())
    }

    fn save_key(&mut self, key_pair: &KeyPairInstance) -> Result<NewKeyId> {
        let id = key_pair.identifier();
        let secret = key_pair.to_secret()?;
        let key_type = key_pair.get_key_type();
        let persisted = KeyPairInstance::from_secret(secret, key_type)?;

        self.keypairs.insert(id.clone(), persisted);

        Ok(NewKeyId {
            id,
            pubkey: key_pair.public(),
        })
    }
}