diff --git a/src/rhai/mod.rs b/src/rhai/mod.rs index cea05e3..f3e380f 100644 --- a/src/rhai/mod.rs +++ b/src/rhai/mod.rs @@ -12,7 +12,7 @@ mod postgresclient; mod process; mod redisclient; mod rfs; -mod hero_vault; // This module now uses hero_vault internally +mod vault; mod text; mod zinit; @@ -111,7 +111,7 @@ pub use crate::text::{ pub use text::*; // Re-export crypto module -pub use hero_vault::register_crypto_module; +pub use vault::register_crypto_module; // Rename copy functions to avoid conflicts pub use os::copy as os_copy; @@ -162,7 +162,7 @@ pub fn register(engine: &mut Engine) -> Result<(), Box> { rfs::register(engine)?; // Register Crypto module functions - hero_vault::register_crypto_module(engine)?; + vault::register_crypto_module(engine)?; // Register Redis client module functions diff --git a/src/rhai/hero_vault.rs b/src/rhai/vault.rs similarity index 96% rename from src/rhai/hero_vault.rs rename to src/rhai/vault.rs index 66ffe26..3f703ee 100644 --- a/src/rhai/hero_vault.rs +++ b/src/rhai/vault.rs @@ -11,9 +11,10 @@ use tokio::runtime::Runtime; use ethers::types::{Address, U256}; use std::str::FromStr; -use crate::vault::{keypair, symmetric, ethereum}; -use crate::vault::ethereum::{prepare_function_arguments, convert_token_to_rhai}; +use crate::vault::{keypair, ethereum}; +use crate::vault::ethereum::contract_utils::{prepare_function_arguments, convert_token_to_rhai}; +use symmetric_impl::implementation as symmetric_impl; // Global Tokio runtime for blocking async operations static RUNTIME: Lazy> = Lazy::new(|| { Mutex::new(Runtime::new().expect("Failed to create Tokio runtime")) @@ -55,7 +56,7 @@ fn load_key_space(name: &str, password: &str) -> bool { }; // Deserialize the encrypted space - let encrypted_space = match symmetric::deserialize_encrypted_space(&serialized) { + let encrypted_space = match symmetric_impl::deserialize_encrypted_space(&serialized) { Ok(space) => space, Err(e) => { log::error!("Error deserializing key space: {}", e); @@ -64,7 +65,7 @@ fn load_key_space(name: &str, password: &str) -> bool { }; // Decrypt the space - let space = match symmetric::decrypt_key_space(&encrypted_space, password) { + let space = match symmetric_impl::decrypt_key_space(&encrypted_space, password) { Ok(space) => space, Err(e) => { log::error!("Error decrypting key space: {}", e); @@ -83,13 +84,13 @@ fn load_key_space(name: &str, password: &str) -> bool { } fn create_key_space(name: &str, password: &str) -> bool { - match keypair::create_space(name) { + match keypair::session_manager::create_space(name) { Ok(_) => { // Get the current space match keypair::get_current_space() { Ok(space) => { // Encrypt the key space - let encrypted_space = match symmetric::encrypt_key_space(&space, password) { + let encrypted_space = match symmetric_impl::encrypt_key_space(&space, password) { Ok(encrypted) => encrypted, Err(e) => { log::error!("Error encrypting key space: {}", e); @@ -98,7 +99,7 @@ fn create_key_space(name: &str, password: &str) -> bool { }; // Serialize the encrypted space - let serialized = match symmetric::serialize_encrypted_space(&encrypted_space) { + let serialized = match symmetric_impl::serialize_encrypted_space(&encrypted_space) { Ok(json) => json, Err(e) => { log::error!("Error serializing encrypted space: {}", e); @@ -152,7 +153,7 @@ fn auto_save_key_space(password: &str) -> bool { match keypair::get_current_space() { Ok(space) => { // Encrypt the key space - let encrypted_space = match symmetric::encrypt_key_space(&space, password) { + let encrypted_space = match symmetric_impl::encrypt_key_space(&space, password) { Ok(encrypted) => encrypted, Err(e) => { log::error!("Error encrypting key space: {}", e); @@ -161,7 +162,7 @@ fn auto_save_key_space(password: &str) -> bool { }; // Serialize the encrypted space - let serialized = match symmetric::serialize_encrypted_space(&encrypted_space) { + let serialized = match symmetric_impl::serialize_encrypted_space(&encrypted_space) { Ok(json) => json, Err(e) => { log::error!("Error serializing encrypted space: {}", e); @@ -207,7 +208,7 @@ fn auto_save_key_space(password: &str) -> bool { fn encrypt_key_space(password: &str) -> String { match keypair::get_current_space() { Ok(space) => { - match symmetric::encrypt_key_space(&space, password) { + match symmetric_impl::encrypt_key_space(&space, password) { Ok(encrypted_space) => { match serde_json::to_string(&encrypted_space) { Ok(json) => json, @@ -233,7 +234,7 @@ fn encrypt_key_space(password: &str) -> String { fn decrypt_key_space(encrypted: &str, password: &str) -> bool { match serde_json::from_str(encrypted) { Ok(encrypted_space) => { - match symmetric::decrypt_key_space(&encrypted_space, password) { + match symmetric_impl::decrypt_key_space(&encrypted_space, password) { Ok(space) => { match keypair::set_current_space(space) { Ok(_) => true, @@ -323,7 +324,7 @@ fn verify(message: &str, signature: &str) -> bool { // Symmetric encryption fn generate_key() -> String { - let key = symmetric::generate_symmetric_key(); + let key = symmetric_impl::generate_symmetric_key(); BASE64.encode(key) } @@ -331,7 +332,7 @@ fn encrypt(key: &str, message: &str) -> String { match BASE64.decode(key) { Ok(key_bytes) => { let message_bytes = message.as_bytes(); - match symmetric::encrypt_symmetric(&key_bytes, message_bytes) { + match symmetric_impl::encrypt_symmetric(&key_bytes, message_bytes) { Ok(ciphertext) => BASE64.encode(ciphertext), Err(e) => { log::error!("Error encrypting message: {}", e); @@ -351,7 +352,7 @@ fn decrypt(key: &str, ciphertext: &str) -> String { Ok(key_bytes) => { match BASE64.decode(ciphertext) { Ok(ciphertext_bytes) => { - match symmetric::decrypt_symmetric(&key_bytes, &ciphertext_bytes) { + match symmetric_impl::decrypt_symmetric(&key_bytes, &ciphertext_bytes) { Ok(plaintext) => { match String::from_utf8(plaintext) { Ok(text) => text, diff --git a/src/vault/ethereum/mod.rs b/src/vault/ethereum/mod.rs index ac698b4..7ec8d32 100644 --- a/src/vault/ethereum/mod.rs +++ b/src/vault/ethereum/mod.rs @@ -16,11 +16,8 @@ mod provider; mod transaction; mod storage; mod contract; -mod contract_utils; +pub mod contract_utils; pub mod networks; -#[cfg(test)] -pub mod tests; - // Re-export public types and functions pub use wallet::EthereumWallet; pub use networks::NetworkConfig; diff --git a/src/vault/ethereum/tests/transaction_tests.rs b/src/vault/ethereum/tests/transaction_tests.rs index 9202434..1fcc01c 100644 --- a/src/vault/ethereum/tests/transaction_tests.rs +++ b/src/vault/ethereum/tests/transaction_tests.rs @@ -1,9 +1,9 @@ //! Tests for Ethereum transaction functionality. use crate::vault::ethereum::*; -use crate::vault::keypair::KeyPair; +use crate::vault::keypair::implementation::KeyPair; use ethers::types::U256; -use std::str::FromStr; +// use std::str::FromStr; #[test] fn test_format_balance() { diff --git a/src/vault/ethereum/tests/wallet_tests.rs b/src/vault/ethereum/tests/wallet_tests.rs index 44f9dd1..eb6502a 100644 --- a/src/vault/ethereum/tests/wallet_tests.rs +++ b/src/vault/ethereum/tests/wallet_tests.rs @@ -1,7 +1,7 @@ //! Tests for Ethereum wallet functionality. use crate::vault::ethereum::*; -use crate::vault::keypair::KeyPair; +use crate::vault::keypair::implementation::KeyPair; use ethers::utils::hex; #[test] @@ -64,7 +64,7 @@ fn test_wallet_management() { clear_ethereum_wallets(); // Create a key space and keypair - crate::vault::keypair::create_space("test_space").unwrap(); + crate::vault::keypair::session_manager::create_space("test_space").unwrap(); crate::vault::keypair::create_keypair("test_keypair3").unwrap(); // Create wallets for different networks diff --git a/src/vault/keypair/README.md b/src/vault/keypair/README.md index b89f9cf..4cfb15d 100644 --- a/src/vault/keypair/README.md +++ b/src/vault/keypair/README.md @@ -6,8 +6,9 @@ The Keypair module provides functionality for creating, managing, and using ECDS The Keypair module is organized into: -- `implementation.rs` - Core implementation of the KeyPair and KeySpace types -- `mod.rs` - Module exports and public interface +- `keypair_types.rs` - Defines the KeyPair and related types. +- `session_manager.rs` - Implements the core logic for managing keypairs and key spaces. +- `mod.rs` - Module exports and public interface. ## Key Types @@ -113,26 +114,44 @@ let mut loaded_space = KeySpace::load("my_space", "secure_password")?; The module provides functionality for creating, selecting, and using keypairs: ```rust -// Create a new keypair in the key space -let keypair = space.create_keypair("my_keypair", "secure_password")?; +use crate::vault::keypair::{KeySpace, KeyPair}; +use crate::vault::error::CryptoError; // Assuming CryptoError is in vault::error -// Select a keypair for use -space.select_keypair("my_keypair")?; +fn demonstrate_keypair_management() -> Result<(), CryptoError> { + // Create a new key space + let mut space = KeySpace::new("my_space", "secure_password")?; -// Get the currently selected keypair -let current = space.current_keypair()?; + // Create a new keypair in the key space + let keypair = space.create_keypair("my_keypair", "secure_password")?; + println!("Created keypair: {}", keypair.public_key().iter().map(|b| format!("{:02x}", b)).collect::()); -// List all keypairs in the key space -let keypairs = space.list_keypairs()?; + // Select a keypair for use + space.select_keypair("my_keypair")?; + println!("Selected keypair: {}", space.current_keypair()?.public_key().iter().map(|b| format!("{:02x}", b)).collect::()); -// Get a keypair by name -let keypair = space.get_keypair("my_keypair")?; + // List all keypairs in the key space + let keypairs = space.list_keypairs()?; + println!("Keypairs in space: {:?}", keypairs); -// Remove a keypair from the key space -space.remove_keypair("my_keypair")?; + // Get a keypair by name + let retrieved_keypair = space.get_keypair("my_keypair")?; + println!("Retrieved keypair: {}", retrieved_keypair.public_key().iter().map(|b| format!("{:02x}", b)).collect::()); -// Rename a keypair -space.rename_keypair("my_keypair", "new_name")?; + // Rename a keypair + space.rename_keypair("my_keypair", "new_name")?; + println!("Renamed keypair to new_name"); + let keypairs_after_rename = space.list_keypairs()?; + println!("Keypairs in space after rename: {:?}", keypairs_after_rename); + + + // Remove a keypair from the key space + space.remove_keypair("new_name")?; + println!("Removed keypair new_name"); + let keypairs_after_remove = space.list_keypairs()?; + println!("Keypairs in space after removal: {:?}", keypairs_after_remove); + + Ok(()) +} ``` ### Digital Signatures @@ -140,12 +159,35 @@ space.rename_keypair("my_keypair", "new_name")?; The module provides functionality for signing and verifying messages using ECDSA: ```rust -// Sign a message using the selected keypair -let keypair = space.current_keypair()?; -let signature = keypair.sign("This is a message to sign".as_bytes())?; +use crate::vault::keypair::KeySpace; +use crate::vault::error::CryptoError; // Assuming CryptoError is in vault::error -// Verify a signature -let is_valid = keypair.verify("This is a message to sign".as_bytes(), &signature)?; +fn demonstrate_digital_signatures() -> Result<(), CryptoError> { + // Assuming a key space and selected keypair exist + // let mut space = KeySpace::load("my_space", "secure_password")?; // Load existing space + let mut space = KeySpace::new("temp_space_for_demo", "password")?; // Or create a new one for demo + space.create_keypair("my_signing_key", "key_password")?; + space.select_keypair("my_signing_key")?; + + + // Sign a message using the selected keypair + let keypair = space.current_keypair()?; + let message = "This is a message to sign".as_bytes(); + let signature = keypair.sign(message)?; + println!("Message signed. Signature: {:?}", signature); + + // Verify a signature + let is_valid = keypair.verify(message, &signature)?; + println!("Signature valid: {}", is_valid); + + // Example of invalid signature verification + let invalid_signature = vec![0u8; signature.len()]; // A dummy invalid signature + let is_valid_invalid = keypair.verify(message, &invalid_signature)?; + println!("Invalid signature valid: {}", is_valid_invalid); + + + Ok(()) +} ``` ### Ethereum Address Derivation @@ -153,11 +195,53 @@ let is_valid = keypair.verify("This is a message to sign".as_bytes(), &signature The module provides functionality for deriving Ethereum addresses from keypairs: ```rust -// Derive an Ethereum address from a keypair -let keypair = space.current_keypair()?; -let address = keypair.to_ethereum_address()?; +use crate::vault::keypair::KeySpace; +use crate::vault::error::CryptoError; // Assuming CryptoError is in vault::error + +fn demonstrate_ethereum_address_derivation() -> Result<(), CryptoError> { + // Assuming a key space and selected keypair exist + // let mut space = KeySpace::load("my_space", "secure_password")?; // Load existing space + let mut space = KeySpace::new("temp_space_for_eth_demo", "password")?; // Or create a new one for demo + space.create_keypair("my_eth_key", "key_password")?; + space.select_keypair("my_eth_key")?; + + // Derive an Ethereum address from a keypair + let keypair = space.current_keypair()?; + let address = keypair.to_ethereum_address()?; + println!("Derived Ethereum address: {}", address); + + Ok(()) +} ``` +## Including in Your Project + +To include the Hero Vault Keypair module in your Rust project, add the following to your `Cargo.toml` file: + +```toml +[dependencies] +hero_vault = "0.1.0" # Replace with the actual version +``` + +Then, you can import and use the module in your Rust code: + +```rust +use hero_vault::vault::keypair::{KeySpace, KeyPair}; +use hero_vault::vault::error::CryptoError; +``` + +## Testing + +Tests for the Keypair module are included within the source files, likely in `session_manager.rs` or `mod.rs` as inline tests. + +To run the tests, navigate to the root directory of the project in your terminal and execute the following command: + +```bash +cargo test --lib vault::keypair +``` + +This command will run all tests specifically within the `vault::keypair` module. + ## Security Considerations - Key spaces are encrypted with ChaCha20Poly1305 using a key derived from the provided password diff --git a/src/vault/keypair/implementation.rs b/src/vault/keypair/keypair_types.rs similarity index 67% rename from src/vault/keypair/implementation.rs rename to src/vault/keypair/keypair_types.rs index ca118ca..cdc5374 100644 --- a/src/vault/keypair/implementation.rs +++ b/src/vault/keypair/keypair_types.rs @@ -1,13 +1,12 @@ -//! Implementation of keypair functionality. +/// Implementation of keypair functionality. use k256::ecdsa::{SigningKey, VerifyingKey, signature::{Signer, Verifier}, Signature}; use rand::rngs::OsRng; use serde::{Serialize, Deserialize}; use std::collections::HashMap; -use once_cell::sync::Lazy; -use std::sync::Mutex; use sha2::{Sha256, Digest}; +use crate::vault::symmetric::implementation; use crate::vault::error::CryptoError; /// A keypair for signing and verifying messages. @@ -226,7 +225,7 @@ impl KeyPair { }; // Encrypt the message using the derived key - let ciphertext = crate::vault::symmetric::encrypt_with_key(&shared_secret, message) + let ciphertext = implementation::encrypt_with_key(&shared_secret, message) .map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?; // Format: ephemeral_public_key || ciphertext @@ -263,7 +262,7 @@ impl KeyPair { }; // Decrypt the message using the derived key - crate::vault::symmetric::decrypt_with_key(&shared_secret, actual_ciphertext) + implementation::decrypt_with_key(&shared_secret, actual_ciphertext) .map_err(|e| CryptoError::DecryptionFailed(e.to_string())) } } @@ -306,162 +305,3 @@ impl KeySpace { } } -/// Session state for the current key space and selected keypair. -pub struct Session { - pub current_space: Option, - pub selected_keypair: Option, -} - -impl Default for Session { - fn default() -> Self { - Session { - current_space: None, - selected_keypair: None, - } - } -} - -/// Global session state. -static SESSION: Lazy> = Lazy::new(|| { - Mutex::new(Session::default()) -}); - -/// Creates a new key space with the given name. -pub fn create_space(name: &str) -> Result<(), CryptoError> { - let mut session = SESSION.lock().unwrap(); - - // Create a new space - let space = KeySpace::new(name); - - // Set as current space - session.current_space = Some(space); - session.selected_keypair = None; - - Ok(()) -} - -/// Sets the current key space. -pub fn set_current_space(space: KeySpace) -> Result<(), CryptoError> { - let mut session = SESSION.lock().unwrap(); - session.current_space = Some(space); - session.selected_keypair = None; - Ok(()) -} - -/// Gets the current key space. -pub fn get_current_space() -> Result { - let session = SESSION.lock().unwrap(); - session.current_space.clone().ok_or(CryptoError::NoActiveSpace) -} - -/// Clears the current session (logout). -pub fn clear_session() { - let mut session = SESSION.lock().unwrap(); - session.current_space = None; - session.selected_keypair = None; -} - -/// Creates a new keypair in the current space. -pub fn create_keypair(name: &str) -> Result<(), CryptoError> { - let mut session = SESSION.lock().unwrap(); - - if let Some(ref mut space) = session.current_space { - if space.keypairs.contains_key(name) { - return Err(CryptoError::KeypairAlreadyExists(name.to_string())); - } - - let keypair = KeyPair::new(name); - space.keypairs.insert(name.to_string(), keypair); - - // Automatically select the new keypair - session.selected_keypair = Some(name.to_string()); - - Ok(()) - } else { - Err(CryptoError::NoActiveSpace) - } -} - -/// Selects a keypair for use. -pub fn select_keypair(name: &str) -> Result<(), CryptoError> { - let mut session = SESSION.lock().unwrap(); - - if let Some(ref space) = session.current_space { - if !space.keypairs.contains_key(name) { - return Err(CryptoError::KeypairNotFound(name.to_string())); - } - - session.selected_keypair = Some(name.to_string()); - Ok(()) - } else { - Err(CryptoError::NoActiveSpace) - } -} - -/// Gets the currently selected keypair. -pub fn get_selected_keypair() -> Result { - let session = SESSION.lock().unwrap(); - - if let Some(ref space) = session.current_space { - if let Some(ref keypair_name) = session.selected_keypair { - if let Some(keypair) = space.keypairs.get(keypair_name) { - return Ok(keypair.clone()); - } - return Err(CryptoError::KeypairNotFound(keypair_name.clone())); - } - return Err(CryptoError::NoKeypairSelected); - } - - Err(CryptoError::NoActiveSpace) -} - -/// Lists all keypair names in the current space. -pub fn list_keypairs() -> Result, CryptoError> { - let session = SESSION.lock().unwrap(); - - if let Some(ref space) = session.current_space { - Ok(space.keypairs.keys().cloned().collect()) - } else { - Err(CryptoError::NoActiveSpace) - } -} - -/// Gets the public key of the selected keypair. -pub fn keypair_pub_key() -> Result, CryptoError> { - let keypair = get_selected_keypair()?; - Ok(keypair.pub_key()) -} - -/// Derives a public key from a private key. -pub fn derive_public_key(private_key: &[u8]) -> Result, CryptoError> { - KeyPair::pub_key_from_private(private_key) -} - -/// Signs a message with the selected keypair. -pub fn keypair_sign(message: &[u8]) -> Result, CryptoError> { - let keypair = get_selected_keypair()?; - Ok(keypair.sign(message)) -} - -/// Verifies a message signature with the selected keypair. -pub fn keypair_verify(message: &[u8], signature_bytes: &[u8]) -> Result { - let keypair = get_selected_keypair()?; - keypair.verify(message, signature_bytes) -} - -/// Verifies a message signature with a public key. -pub fn verify_with_public_key(public_key: &[u8], message: &[u8], signature_bytes: &[u8]) -> Result { - KeyPair::verify_with_public_key(public_key, message, signature_bytes) -} - -/// Encrypts a message for a recipient using their public key. -pub fn encrypt_asymmetric(recipient_public_key: &[u8], message: &[u8]) -> Result, CryptoError> { - let keypair = get_selected_keypair()?; - keypair.encrypt_asymmetric(recipient_public_key, message) -} - -/// Decrypts a message that was encrypted with the current keypair's public key. -pub fn decrypt_asymmetric(ciphertext: &[u8]) -> Result, CryptoError> { - let keypair = get_selected_keypair()?; - keypair.decrypt_asymmetric(ciphertext) -} diff --git a/src/vault/keypair/mod.rs b/src/vault/keypair/mod.rs index 016b7f2..e29506b 100644 --- a/src/vault/keypair/mod.rs +++ b/src/vault/keypair/mod.rs @@ -2,11 +2,12 @@ //! //! This module provides functionality for creating and managing ECDSA key pairs. -mod implementation; +pub mod keypair_types; +pub mod session_manager; // Re-export public types and functions -pub use implementation::{ - KeyPair, KeySpace, +pub use keypair_types::{KeyPair, KeySpace}; +pub use session_manager::{ create_space, set_current_space, get_current_space, clear_session, create_keypair, select_keypair, get_selected_keypair, list_keypairs, keypair_pub_key, derive_public_key, keypair_sign, keypair_verify, diff --git a/src/vault/keypair/session_manager.rs b/src/vault/keypair/session_manager.rs new file mode 100644 index 0000000..32ac9a7 --- /dev/null +++ b/src/vault/keypair/session_manager.rs @@ -0,0 +1,169 @@ +use serde::{Serialize, Deserialize}; +use std::collections::HashMap; +use once_cell::sync::Lazy; +use std::sync::Mutex; + +use crate::vault::error::CryptoError; +use crate::vault::keypair::keypair_types::{KeyPair, KeySpace}; // Assuming KeyPair and KeySpace will be in keypair_types.rs +use crate::vault::symmetric; // Assuming symmetric module is needed + +/// Session state for the current key space and selected keypair. +pub struct Session { + pub current_space: Option, + pub selected_keypair: Option, +} + +impl Default for Session { + fn default() -> Self { + Session { + current_space: None, + selected_keypair: None, + } + } +} + +/// Global session state. +pub static SESSION: Lazy> = Lazy::new(|| { + Mutex::new(Session::default()) +}); + +// Session management and selected keypair operation functions will be added here +/// Creates a new key space with the given name. +pub fn create_space(name: &str) -> Result<(), CryptoError> { + let mut session = SESSION.lock().unwrap(); + + // Create a new space + let space = KeySpace::new(name); + + // Set as current space + session.current_space = Some(space); + session.selected_keypair = None; + + Ok(()) +} + +/// Sets the current key space. +pub fn set_current_space(space: KeySpace) -> Result<(), CryptoError> { + let mut session = SESSION.lock().unwrap(); + session.current_space = Some(space); + session.selected_keypair = None; + Ok(()) +} + +/// Gets the current key space. +pub fn get_current_space() -> Result { + let session = SESSION.lock().unwrap(); + session.current_space.clone().ok_or(CryptoError::NoActiveSpace) +} + +/// Clears the current session (logout). +pub fn clear_session() { + let mut session = SESSION.lock().unwrap(); + session.current_space = None; + session.selected_keypair = None; +} + +/// Creates a new keypair in the current space. +pub fn create_keypair(name: &str) -> Result<(), CryptoError> { + let mut session = SESSION.lock().unwrap(); + + if let Some(ref mut space) = session.current_space { + if space.keypairs.contains_key(name) { + return Err(CryptoError::KeypairAlreadyExists(name.to_string())); + } + + let keypair = KeyPair::new(name); + space.keypairs.insert(name.to_string(), keypair); + + // Automatically select the new keypair + session.selected_keypair = Some(name.to_string()); + + Ok(()) + } else { + Err(CryptoError::NoActiveSpace) + } +} + +/// Selects a keypair for use. +pub fn select_keypair(name: &str) -> Result<(), CryptoError> { + let mut session = SESSION.lock().unwrap(); + + if let Some(ref space) = session.current_space { + if !space.keypairs.contains_key(name) { + return Err(CryptoError::KeypairNotFound(name.to_string())); + } + + session.selected_keypair = Some(name.to_string()); + Ok(()) + } else { + Err(CryptoError::NoActiveSpace) + } +} + +/// Gets the currently selected keypair. +pub fn get_selected_keypair() -> Result { + let session = SESSION.lock().unwrap(); + + if let Some(ref space) = session.current_space { + if let Some(ref keypair_name) = session.selected_keypair { + if let Some(keypair) = space.keypairs.get(keypair_name) { + return Ok(keypair.clone()); + } + return Err(CryptoError::KeypairNotFound(keypair_name.clone())); + } + return Err(CryptoError::NoKeypairSelected); + } + + Err(CryptoError::NoActiveSpace) +} + +/// Lists all keypair names in the current space. +pub fn list_keypairs() -> Result, CryptoError> { + let session = SESSION.lock().unwrap(); + + if let Some(ref space) = session.current_space { + Ok(space.keypairs.keys().cloned().collect()) + } else { + Err(CryptoError::NoActiveSpace) + } +} + +/// Gets the public key of the selected keypair. +pub fn keypair_pub_key() -> Result, CryptoError> { + let keypair = get_selected_keypair()?; + Ok(keypair.pub_key()) +} + +/// Derives a public key from a private key. +pub fn derive_public_key(private_key: &[u8]) -> Result, CryptoError> { + KeyPair::pub_key_from_private(private_key) +} + +/// Signs a message with the selected keypair. +pub fn keypair_sign(message: &[u8]) -> Result, CryptoError> { + let keypair = get_selected_keypair()?; + Ok(keypair.sign(message)) +} + +/// Verifies a message signature with the selected keypair. +pub fn keypair_verify(message: &[u8], signature_bytes: &[u8]) -> Result { + let keypair = get_selected_keypair()?; + keypair.verify(message, signature_bytes) +} + +/// Verifies a message signature with a public key. +pub fn verify_with_public_key(public_key: &[u8], message: &[u8], signature_bytes: &[u8]) -> Result { + KeyPair::verify_with_public_key(public_key, message, signature_bytes) +} + +/// Encrypts a message for a recipient using their public key. +pub fn encrypt_asymmetric(recipient_public_key: &[u8], message: &[u8]) -> Result, CryptoError> { + let keypair = get_selected_keypair()?; + keypair.encrypt_asymmetric(recipient_public_key, message) +} + +/// Decrypts a message that was encrypted with the current keypair's public key. +pub fn decrypt_asymmetric(ciphertext: &[u8]) -> Result, CryptoError> { + let keypair = get_selected_keypair()?; + keypair.decrypt_asymmetric(ciphertext) +} \ No newline at end of file diff --git a/src/vault/kvs/mod.rs b/src/vault/kvs/mod.rs index 890333d..4ab3770 100644 --- a/src/vault/kvs/mod.rs +++ b/src/vault/kvs/mod.rs @@ -2,8 +2,8 @@ //! //! This module provides a simple key-value store with encryption support. -mod error; -mod store; +pub mod error; +pub mod store; // Re-export public types and functions pub use error::KvsError; diff --git a/src/vault/kvs/store.rs b/src/vault/kvs/store.rs index 2f8b8c6..775fcdc 100644 --- a/src/vault/kvs/store.rs +++ b/src/vault/kvs/store.rs @@ -1,11 +1,11 @@ //! Implementation of a simple key-value store using the filesystem. use crate::vault::kvs::error::{KvsError, Result}; -use crate::vault::symmetric; +use crate::vault::symmetric::implementation::{derive_key_from_password, encrypt_symmetric, decrypt_symmetric}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::collections::HashMap; use std::fs; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; /// A key-value pair. @@ -115,8 +115,8 @@ pub fn open_store(name: &str, password: Option<&str>) -> Result { // Decrypt the file content let password = password.unwrap(); let encrypted_data: Vec = serde_json::from_str(&file_content)?; - let key = symmetric::derive_key_from_password(password); - let decrypted_data = symmetric::decrypt_symmetric(&key, &encrypted_data)?; + let key = implementation::derive_key_from_password(password); + let decrypted_data = implementation::decrypt_symmetric(&key, &encrypted_data)?; let decrypted_str = String::from_utf8(decrypted_data) .map_err(|e| KvsError::Deserialization(e.to_string()))?; serde_json::from_str(&decrypted_str)? @@ -203,8 +203,8 @@ impl KvStore { if self.encrypted { if let Some(password) = &self.password { // Encrypt the data - let key = symmetric::derive_key_from_password(password); - let encrypted_data = symmetric::encrypt_symmetric(&key, serialized.as_bytes())?; + let key = implementation::derive_key_from_password(password); + let encrypted_data = implementation::encrypt_symmetric(&key, serialized.as_bytes())?; let encrypted_json = serde_json::to_string(&encrypted_data)?; fs::write(&self.path, encrypted_json)?; } else { @@ -263,10 +263,10 @@ impl KvStore { { let key_str = key.to_string(); let data = self.data.lock().unwrap(); - + match data.get(&key_str) { Some(serialized) => { - let value = serde_json::from_str(serialized)?; + let value: V = serde_json::from_str(serialized)?; Ok(value) }, None => Err(KvsError::KeyNotFound(key_str)), diff --git a/src/vault/mod.rs b/src/vault/mod.rs index 0a301ca..130333c 100644 --- a/src/vault/mod.rs +++ b/src/vault/mod.rs @@ -14,6 +14,7 @@ pub mod symmetric; pub mod ethereum; pub mod kvs; +// Re-export modules // Re-export common types for convenience pub use error::CryptoError; pub use keypair::{KeyPair, KeySpace}; diff --git a/src/vault/symmetric/mod.rs b/src/vault/symmetric/mod.rs index 5b2f24a..1d63e3e 100644 --- a/src/vault/symmetric/mod.rs +++ b/src/vault/symmetric/mod.rs @@ -2,7 +2,7 @@ //! //! This module provides functionality for symmetric encryption using ChaCha20Poly1305. -mod implementation; +pub mod implementation; // Re-export public types and functions pub use implementation::{