...
Some checks are pending
Rhai Tests / Run Rhai Tests (push) Waiting to run

This commit is contained in:
despiegk 2025-05-12 12:16:03 +03:00
parent e47e163285
commit a8ed0900fd
13 changed files with 320 additions and 227 deletions

View File

@ -12,7 +12,7 @@ mod postgresclient;
mod process; mod process;
mod redisclient; mod redisclient;
mod rfs; mod rfs;
mod hero_vault; // This module now uses hero_vault internally mod vault;
mod text; mod text;
mod zinit; mod zinit;
@ -111,7 +111,7 @@ pub use crate::text::{
pub use text::*; pub use text::*;
// Re-export crypto module // Re-export crypto module
pub use hero_vault::register_crypto_module; pub use vault::register_crypto_module;
// Rename copy functions to avoid conflicts // Rename copy functions to avoid conflicts
pub use os::copy as os_copy; pub use os::copy as os_copy;
@ -162,7 +162,7 @@ pub fn register(engine: &mut Engine) -> Result<(), Box<rhai::EvalAltResult>> {
rfs::register(engine)?; rfs::register(engine)?;
// Register Crypto module functions // Register Crypto module functions
hero_vault::register_crypto_module(engine)?; vault::register_crypto_module(engine)?;
// Register Redis client module functions // Register Redis client module functions

View File

@ -11,9 +11,10 @@ use tokio::runtime::Runtime;
use ethers::types::{Address, U256}; use ethers::types::{Address, U256};
use std::str::FromStr; use std::str::FromStr;
use crate::vault::{keypair, symmetric, ethereum}; use crate::vault::{keypair, ethereum};
use crate::vault::ethereum::{prepare_function_arguments, convert_token_to_rhai}; 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 // Global Tokio runtime for blocking async operations
static RUNTIME: Lazy<Mutex<Runtime>> = Lazy::new(|| { static RUNTIME: Lazy<Mutex<Runtime>> = Lazy::new(|| {
Mutex::new(Runtime::new().expect("Failed to create Tokio runtime")) 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 // 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, Ok(space) => space,
Err(e) => { Err(e) => {
log::error!("Error deserializing key space: {}", e); log::error!("Error deserializing key space: {}", e);
@ -64,7 +65,7 @@ fn load_key_space(name: &str, password: &str) -> bool {
}; };
// Decrypt the space // 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, Ok(space) => space,
Err(e) => { Err(e) => {
log::error!("Error decrypting key space: {}", 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 { fn create_key_space(name: &str, password: &str) -> bool {
match keypair::create_space(name) { match keypair::session_manager::create_space(name) {
Ok(_) => { Ok(_) => {
// Get the current space // Get the current space
match keypair::get_current_space() { match keypair::get_current_space() {
Ok(space) => { Ok(space) => {
// Encrypt the key 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, Ok(encrypted) => encrypted,
Err(e) => { Err(e) => {
log::error!("Error encrypting key space: {}", 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 // 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, Ok(json) => json,
Err(e) => { Err(e) => {
log::error!("Error serializing encrypted space: {}", 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() { match keypair::get_current_space() {
Ok(space) => { Ok(space) => {
// Encrypt the key 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, Ok(encrypted) => encrypted,
Err(e) => { Err(e) => {
log::error!("Error encrypting key space: {}", e); log::error!("Error encrypting key space: {}", e);
@ -161,7 +162,7 @@ fn auto_save_key_space(password: &str) -> bool {
}; };
// Serialize the encrypted space // 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, Ok(json) => json,
Err(e) => { Err(e) => {
log::error!("Error serializing encrypted space: {}", 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 { fn encrypt_key_space(password: &str) -> String {
match keypair::get_current_space() { match keypair::get_current_space() {
Ok(space) => { Ok(space) => {
match symmetric::encrypt_key_space(&space, password) { match symmetric_impl::encrypt_key_space(&space, password) {
Ok(encrypted_space) => { Ok(encrypted_space) => {
match serde_json::to_string(&encrypted_space) { match serde_json::to_string(&encrypted_space) {
Ok(json) => json, Ok(json) => json,
@ -233,7 +234,7 @@ fn encrypt_key_space(password: &str) -> String {
fn decrypt_key_space(encrypted: &str, password: &str) -> bool { fn decrypt_key_space(encrypted: &str, password: &str) -> bool {
match serde_json::from_str(encrypted) { match serde_json::from_str(encrypted) {
Ok(encrypted_space) => { Ok(encrypted_space) => {
match symmetric::decrypt_key_space(&encrypted_space, password) { match symmetric_impl::decrypt_key_space(&encrypted_space, password) {
Ok(space) => { Ok(space) => {
match keypair::set_current_space(space) { match keypair::set_current_space(space) {
Ok(_) => true, Ok(_) => true,
@ -323,7 +324,7 @@ fn verify(message: &str, signature: &str) -> bool {
// Symmetric encryption // Symmetric encryption
fn generate_key() -> String { fn generate_key() -> String {
let key = symmetric::generate_symmetric_key(); let key = symmetric_impl::generate_symmetric_key();
BASE64.encode(key) BASE64.encode(key)
} }
@ -331,7 +332,7 @@ fn encrypt(key: &str, message: &str) -> String {
match BASE64.decode(key) { match BASE64.decode(key) {
Ok(key_bytes) => { Ok(key_bytes) => {
let message_bytes = message.as_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), Ok(ciphertext) => BASE64.encode(ciphertext),
Err(e) => { Err(e) => {
log::error!("Error encrypting message: {}", e); log::error!("Error encrypting message: {}", e);
@ -351,7 +352,7 @@ fn decrypt(key: &str, ciphertext: &str) -> String {
Ok(key_bytes) => { Ok(key_bytes) => {
match BASE64.decode(ciphertext) { match BASE64.decode(ciphertext) {
Ok(ciphertext_bytes) => { Ok(ciphertext_bytes) => {
match symmetric::decrypt_symmetric(&key_bytes, &ciphertext_bytes) { match symmetric_impl::decrypt_symmetric(&key_bytes, &ciphertext_bytes) {
Ok(plaintext) => { Ok(plaintext) => {
match String::from_utf8(plaintext) { match String::from_utf8(plaintext) {
Ok(text) => text, Ok(text) => text,

View File

@ -16,11 +16,8 @@ mod provider;
mod transaction; mod transaction;
mod storage; mod storage;
mod contract; mod contract;
mod contract_utils; pub mod contract_utils;
pub mod networks; pub mod networks;
#[cfg(test)]
pub mod tests;
// Re-export public types and functions // Re-export public types and functions
pub use wallet::EthereumWallet; pub use wallet::EthereumWallet;
pub use networks::NetworkConfig; pub use networks::NetworkConfig;

View File

@ -1,9 +1,9 @@
//! Tests for Ethereum transaction functionality. //! Tests for Ethereum transaction functionality.
use crate::vault::ethereum::*; use crate::vault::ethereum::*;
use crate::vault::keypair::KeyPair; use crate::vault::keypair::implementation::KeyPair;
use ethers::types::U256; use ethers::types::U256;
use std::str::FromStr; // use std::str::FromStr;
#[test] #[test]
fn test_format_balance() { fn test_format_balance() {

View File

@ -1,7 +1,7 @@
//! Tests for Ethereum wallet functionality. //! Tests for Ethereum wallet functionality.
use crate::vault::ethereum::*; use crate::vault::ethereum::*;
use crate::vault::keypair::KeyPair; use crate::vault::keypair::implementation::KeyPair;
use ethers::utils::hex; use ethers::utils::hex;
#[test] #[test]
@ -64,7 +64,7 @@ fn test_wallet_management() {
clear_ethereum_wallets(); clear_ethereum_wallets();
// Create a key space and keypair // 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(); crate::vault::keypair::create_keypair("test_keypair3").unwrap();
// Create wallets for different networks // Create wallets for different networks

View File

@ -6,8 +6,9 @@ The Keypair module provides functionality for creating, managing, and using ECDS
The Keypair module is organized into: The Keypair module is organized into:
- `implementation.rs` - Core implementation of the KeyPair and KeySpace types - `keypair_types.rs` - Defines the KeyPair and related types.
- `mod.rs` - Module exports and public interface - `session_manager.rs` - Implements the core logic for managing keypairs and key spaces.
- `mod.rs` - Module exports and public interface.
## Key Types ## 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: The module provides functionality for creating, selecting, and using keypairs:
```rust ```rust
// Create a new keypair in the key space use crate::vault::keypair::{KeySpace, KeyPair};
let keypair = space.create_keypair("my_keypair", "secure_password")?; use crate::vault::error::CryptoError; // Assuming CryptoError is in vault::error
// Select a keypair for use fn demonstrate_keypair_management() -> Result<(), CryptoError> {
space.select_keypair("my_keypair")?; // Create a new key space
let mut space = KeySpace::new("my_space", "secure_password")?;
// Get the currently selected keypair // Create a new keypair in the key space
let current = space.current_keypair()?; let keypair = space.create_keypair("my_keypair", "secure_password")?;
println!("Created keypair: {}", keypair.public_key().iter().map(|b| format!("{:02x}", b)).collect::<String>());
// List all keypairs in the key space // Select a keypair for use
let keypairs = space.list_keypairs()?; space.select_keypair("my_keypair")?;
println!("Selected keypair: {}", space.current_keypair()?.public_key().iter().map(|b| format!("{:02x}", b)).collect::<String>());
// Get a keypair by name // List all keypairs in the key space
let keypair = space.get_keypair("my_keypair")?; let keypairs = space.list_keypairs()?;
println!("Keypairs in space: {:?}", keypairs);
// Remove a keypair from the key space // Get a keypair by name
space.remove_keypair("my_keypair")?; let retrieved_keypair = space.get_keypair("my_keypair")?;
println!("Retrieved keypair: {}", retrieved_keypair.public_key().iter().map(|b| format!("{:02x}", b)).collect::<String>());
// Rename a keypair // Rename a keypair
space.rename_keypair("my_keypair", "new_name")?; 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 ### Digital Signatures
@ -140,12 +159,35 @@ space.rename_keypair("my_keypair", "new_name")?;
The module provides functionality for signing and verifying messages using ECDSA: The module provides functionality for signing and verifying messages using ECDSA:
```rust ```rust
// Sign a message using the selected keypair use crate::vault::keypair::KeySpace;
let keypair = space.current_keypair()?; use crate::vault::error::CryptoError; // Assuming CryptoError is in vault::error
let signature = keypair.sign("This is a message to sign".as_bytes())?;
// Verify a signature fn demonstrate_digital_signatures() -> Result<(), CryptoError> {
let is_valid = keypair.verify("This is a message to sign".as_bytes(), &signature)?; // 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 ### 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: The module provides functionality for deriving Ethereum addresses from keypairs:
```rust ```rust
// Derive an Ethereum address from a keypair use crate::vault::keypair::KeySpace;
let keypair = space.current_keypair()?; use crate::vault::error::CryptoError; // Assuming CryptoError is in vault::error
let address = keypair.to_ethereum_address()?;
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 ## Security Considerations
- Key spaces are encrypted with ChaCha20Poly1305 using a key derived from the provided password - Key spaces are encrypted with ChaCha20Poly1305 using a key derived from the provided password

View File

@ -1,13 +1,12 @@
//! Implementation of keypair functionality. /// Implementation of keypair functionality.
use k256::ecdsa::{SigningKey, VerifyingKey, signature::{Signer, Verifier}, Signature}; use k256::ecdsa::{SigningKey, VerifyingKey, signature::{Signer, Verifier}, Signature};
use rand::rngs::OsRng; use rand::rngs::OsRng;
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use std::collections::HashMap; use std::collections::HashMap;
use once_cell::sync::Lazy;
use std::sync::Mutex;
use sha2::{Sha256, Digest}; use sha2::{Sha256, Digest};
use crate::vault::symmetric::implementation;
use crate::vault::error::CryptoError; use crate::vault::error::CryptoError;
/// A keypair for signing and verifying messages. /// A keypair for signing and verifying messages.
@ -226,7 +225,7 @@ impl KeyPair {
}; };
// Encrypt the message using the derived key // 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()))?; .map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?;
// Format: ephemeral_public_key || ciphertext // Format: ephemeral_public_key || ciphertext
@ -263,7 +262,7 @@ impl KeyPair {
}; };
// Decrypt the message using the derived key // 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())) .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<KeySpace>,
pub selected_keypair: Option<String>,
}
impl Default for Session {
fn default() -> Self {
Session {
current_space: None,
selected_keypair: None,
}
}
}
/// Global session state.
static SESSION: Lazy<Mutex<Session>> = 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<KeySpace, CryptoError> {
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<KeyPair, CryptoError> {
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<Vec<String>, 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<Vec<u8>, 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<Vec<u8>, CryptoError> {
KeyPair::pub_key_from_private(private_key)
}
/// Signs a message with the selected keypair.
pub fn keypair_sign(message: &[u8]) -> Result<Vec<u8>, 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<bool, CryptoError> {
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<bool, CryptoError> {
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<Vec<u8>, 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<Vec<u8>, CryptoError> {
let keypair = get_selected_keypair()?;
keypair.decrypt_asymmetric(ciphertext)
}

View File

@ -2,11 +2,12 @@
//! //!
//! This module provides functionality for creating and managing ECDSA key pairs. //! 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 // Re-export public types and functions
pub use implementation::{ pub use keypair_types::{KeyPair, KeySpace};
KeyPair, KeySpace, pub use session_manager::{
create_space, set_current_space, get_current_space, clear_session, create_space, set_current_space, get_current_space, clear_session,
create_keypair, select_keypair, get_selected_keypair, list_keypairs, create_keypair, select_keypair, get_selected_keypair, list_keypairs,
keypair_pub_key, derive_public_key, keypair_sign, keypair_verify, keypair_pub_key, derive_public_key, keypair_sign, keypair_verify,

View File

@ -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<KeySpace>,
pub selected_keypair: Option<String>,
}
impl Default for Session {
fn default() -> Self {
Session {
current_space: None,
selected_keypair: None,
}
}
}
/// Global session state.
pub static SESSION: Lazy<Mutex<Session>> = 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<KeySpace, CryptoError> {
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<KeyPair, CryptoError> {
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<Vec<String>, 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<Vec<u8>, 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<Vec<u8>, CryptoError> {
KeyPair::pub_key_from_private(private_key)
}
/// Signs a message with the selected keypair.
pub fn keypair_sign(message: &[u8]) -> Result<Vec<u8>, 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<bool, CryptoError> {
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<bool, CryptoError> {
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<Vec<u8>, 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<Vec<u8>, CryptoError> {
let keypair = get_selected_keypair()?;
keypair.decrypt_asymmetric(ciphertext)
}

View File

@ -2,8 +2,8 @@
//! //!
//! This module provides a simple key-value store with encryption support. //! This module provides a simple key-value store with encryption support.
mod error; pub mod error;
mod store; pub mod store;
// Re-export public types and functions // Re-export public types and functions
pub use error::KvsError; pub use error::KvsError;

View File

@ -1,11 +1,11 @@
//! Implementation of a simple key-value store using the filesystem. //! Implementation of a simple key-value store using the filesystem.
use crate::vault::kvs::error::{KvsError, Result}; 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 serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::fs;
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
/// A key-value pair. /// A key-value pair.
@ -115,8 +115,8 @@ pub fn open_store(name: &str, password: Option<&str>) -> Result<KvStore> {
// Decrypt the file content // Decrypt the file content
let password = password.unwrap(); let password = password.unwrap();
let encrypted_data: Vec<u8> = serde_json::from_str(&file_content)?; let encrypted_data: Vec<u8> = serde_json::from_str(&file_content)?;
let key = symmetric::derive_key_from_password(password); let key = implementation::derive_key_from_password(password);
let decrypted_data = symmetric::decrypt_symmetric(&key, &encrypted_data)?; let decrypted_data = implementation::decrypt_symmetric(&key, &encrypted_data)?;
let decrypted_str = String::from_utf8(decrypted_data) let decrypted_str = String::from_utf8(decrypted_data)
.map_err(|e| KvsError::Deserialization(e.to_string()))?; .map_err(|e| KvsError::Deserialization(e.to_string()))?;
serde_json::from_str(&decrypted_str)? serde_json::from_str(&decrypted_str)?
@ -203,8 +203,8 @@ impl KvStore {
if self.encrypted { if self.encrypted {
if let Some(password) = &self.password { if let Some(password) = &self.password {
// Encrypt the data // Encrypt the data
let key = symmetric::derive_key_from_password(password); let key = implementation::derive_key_from_password(password);
let encrypted_data = symmetric::encrypt_symmetric(&key, serialized.as_bytes())?; let encrypted_data = implementation::encrypt_symmetric(&key, serialized.as_bytes())?;
let encrypted_json = serde_json::to_string(&encrypted_data)?; let encrypted_json = serde_json::to_string(&encrypted_data)?;
fs::write(&self.path, encrypted_json)?; fs::write(&self.path, encrypted_json)?;
} else { } else {
@ -263,10 +263,10 @@ impl KvStore {
{ {
let key_str = key.to_string(); let key_str = key.to_string();
let data = self.data.lock().unwrap(); let data = self.data.lock().unwrap();
match data.get(&key_str) { match data.get(&key_str) {
Some(serialized) => { Some(serialized) => {
let value = serde_json::from_str(serialized)?; let value: V = serde_json::from_str(serialized)?;
Ok(value) Ok(value)
}, },
None => Err(KvsError::KeyNotFound(key_str)), None => Err(KvsError::KeyNotFound(key_str)),

View File

@ -14,6 +14,7 @@ pub mod symmetric;
pub mod ethereum; pub mod ethereum;
pub mod kvs; pub mod kvs;
// Re-export modules
// Re-export common types for convenience // Re-export common types for convenience
pub use error::CryptoError; pub use error::CryptoError;
pub use keypair::{KeyPair, KeySpace}; pub use keypair::{KeyPair, KeySpace};

View File

@ -2,7 +2,7 @@
//! //!
//! This module provides functionality for symmetric encryption using ChaCha20Poly1305. //! This module provides functionality for symmetric encryption using ChaCha20Poly1305.
mod implementation; pub mod implementation;
// Re-export public types and functions // Re-export public types and functions
pub use implementation::{ pub use implementation::{