This commit is contained in:
parent
e47e163285
commit
a8ed0900fd
@ -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<rhai::EvalAltResult>> {
|
||||
rfs::register(engine)?;
|
||||
|
||||
// Register Crypto module functions
|
||||
hero_vault::register_crypto_module(engine)?;
|
||||
vault::register_crypto_module(engine)?;
|
||||
|
||||
|
||||
// Register Redis client module functions
|
||||
|
@ -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<Mutex<Runtime>> = 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,
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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::<String>());
|
||||
|
||||
// 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::<String>());
|
||||
|
||||
// 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::<String>());
|
||||
|
||||
// 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
|
||||
|
@ -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<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)
|
||||
}
|
@ -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,
|
||||
|
169
src/vault/keypair/session_manager.rs
Normal file
169
src/vault/keypair/session_manager.rs
Normal 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)
|
||||
}
|
@ -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;
|
||||
|
@ -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<KvStore> {
|
||||
// Decrypt the file content
|
||||
let password = password.unwrap();
|
||||
let encrypted_data: Vec<u8> = 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)),
|
||||
|
@ -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};
|
||||
|
@ -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::{
|
||||
|
Loading…
Reference in New Issue
Block a user