diff --git a/src/rhai/vault.rs b/src/rhai/vault.rs index 42f68d4..2286afa 100644 --- a/src/rhai/vault.rs +++ b/src/rhai/vault.rs @@ -12,7 +12,7 @@ use std::sync::Mutex; use tokio::runtime::Runtime; use crate::vault::ethereum::contract_utils::{convert_token_to_rhai, prepare_function_arguments}; -use crate::vault::{ethereum, keypair}; +use crate::vault::{ethereum, keyspace}; use crate::vault::symmetric::implementation as symmetric_impl; // Global Tokio runtime for blocking async operations @@ -73,7 +73,7 @@ fn load_key_space(name: &str, password: &str) -> bool { }; // Set as current space - match keypair::set_current_space(space) { + match keyspace::set_current_space(space) { Ok(_) => true, Err(e) => { log::error!("Error setting current space: {}", e); @@ -83,10 +83,10 @@ fn load_key_space(name: &str, password: &str) -> bool { } fn create_key_space(name: &str, password: &str) -> bool { - match keypair::session_manager::create_space(name) { + match keyspace::session_manager::create_space(name) { Ok(_) => { // Get the current space - match keypair::get_current_space() { + match keyspace::get_current_space() { Ok(space) => { // Encrypt the key space let encrypted_space = match symmetric_impl::encrypt_key_space(&space, password) @@ -151,7 +151,7 @@ fn create_key_space(name: &str, password: &str) -> bool { // Auto-save function for internal use fn auto_save_key_space(password: &str) -> bool { - match keypair::get_current_space() { + match keyspace::get_current_space() { Ok(space) => { // Encrypt the key space let encrypted_space = match symmetric_impl::encrypt_key_space(&space, password) { @@ -207,7 +207,7 @@ fn auto_save_key_space(password: &str) -> bool { } fn encrypt_key_space(password: &str) -> String { - match keypair::get_current_space() { + match keyspace::get_current_space() { Ok(space) => match symmetric_impl::encrypt_key_space(&space, password) { Ok(encrypted_space) => match serde_json::to_string(&encrypted_space) { Ok(json) => json, @@ -232,7 +232,7 @@ fn decrypt_key_space(encrypted: &str, password: &str) -> bool { match serde_json::from_str(encrypted) { Ok(encrypted_space) => { match symmetric_impl::decrypt_key_space(&encrypted_space, password) { - Ok(space) => match keypair::set_current_space(space) { + Ok(space) => match keyspace::set_current_space(space) { Ok(_) => true, Err(e) => { log::error!("Error setting current space: {}", e); @@ -252,35 +252,35 @@ fn decrypt_key_space(encrypted: &str, password: &str) -> bool { } } -// Keypair management functions -fn create_keypair(name: &str, password: &str) -> bool { - match keypair::create_keypair(name) { +// keyspace management functions +fn create_keyspace(name: &str, password: &str) -> bool { + match keyspace::create_keypair(name) { Ok(_) => { - // Auto-save the key space after creating a keypair + // Auto-save the key space after creating a keyspace auto_save_key_space(password) } Err(e) => { - log::error!("Error creating keypair: {}", e); + log::error!("Error creating keyspace: {}", e); false } } } -fn select_keypair(name: &str) -> bool { - match keypair::select_keypair(name) { +fn select_keyspace(name: &str) -> bool { + match keyspace::select_keypair(name) { Ok(_) => true, Err(e) => { - log::error!("Error selecting keypair: {}", e); + log::error!("Error selecting keyspace: {}", e); false } } } -fn list_keypairs() -> Vec { - match keypair::list_keypairs() { - Ok(keypairs) => keypairs, +fn list_keyspaces() -> Vec { + match keyspace::list_keypairs() { + Ok(keyspaces) => keyspaces, Err(e) => { - log::error!("Error listing keypairs: {}", e); + log::error!("Error listing keyspaces: {}", e); Vec::new() } } @@ -289,7 +289,7 @@ fn list_keypairs() -> Vec { // Cryptographic operations fn sign(message: &str) -> String { let message_bytes = message.as_bytes(); - match keypair::keypair_sign(message_bytes) { + match keyspace::keypair_sign(message_bytes) { Ok(signature) => BASE64.encode(signature), Err(e) => { log::error!("Error signing message: {}", e); @@ -301,7 +301,7 @@ fn sign(message: &str) -> String { fn verify(message: &str, signature: &str) -> bool { let message_bytes = message.as_bytes(); match BASE64.decode(signature) { - Ok(signature_bytes) => match keypair::keypair_verify(message_bytes, &signature_bytes) { + Ok(signature_bytes) => match keyspace::keypair_verify(message_bytes, &signature_bytes) { Ok(is_valid) => is_valid, Err(e) => { log::error!("Error verifying signature: {}", e); @@ -881,10 +881,10 @@ pub fn register_crypto_module(engine: &mut Engine) -> Result<(), Box Result { // Get the private key bytes from the keypair let private_key_bytes = keypair.signing_key.to_bytes(); - + // Convert to a hex string (without 0x prefix) let private_key_hex = hex::encode(private_key_bytes); - + // Create an Ethereum wallet from the private key let wallet = LocalWallet::from_str(&private_key_hex) .map_err(|_e| CryptoError::InvalidKeyLength)? .with_chain_id(network.chain_id); - + // Get the Ethereum address let address = wallet.address(); - + Ok(EthereumWallet { address, wallet, network, }) } - + /// Creates a new Ethereum wallet from a name and keypair (deterministic derivation) for a specific network. - pub fn from_name_and_keypair(name: &str, keypair: &KeyPair, network: NetworkConfig) -> Result { + pub fn from_name_and_keypair( + name: &str, + keypair: &KeyPair, + network: NetworkConfig, + ) -> Result { // Get the private key bytes from the keypair let private_key_bytes = keypair.signing_key.to_bytes(); - + // Create a deterministic seed by combining name and private key let mut hasher = Sha256::default(); hasher.update(name.as_bytes()); hasher.update(&private_key_bytes); let seed = hasher.finalize(); - + // Use the seed as a private key let private_key_hex = hex::encode(seed); - + // Create an Ethereum wallet from the derived private key let wallet = LocalWallet::from_str(&private_key_hex) .map_err(|_e| CryptoError::InvalidKeyLength)? .with_chain_id(network.chain_id); - + // Get the Ethereum address let address = wallet.address(); - + Ok(EthereumWallet { address, wallet, network, }) } - + /// Creates a new Ethereum wallet from a private key for a specific network. - pub fn from_private_key(private_key: &str, network: NetworkConfig) -> Result { + pub fn from_private_key( + private_key: &str, + network: NetworkConfig, + ) -> Result { // Remove 0x prefix if present let private_key_clean = private_key.trim_start_matches("0x"); - + // Create an Ethereum wallet from the private key let wallet = LocalWallet::from_str(private_key_clean) .map_err(|_e| CryptoError::InvalidKeyLength)? .with_chain_id(network.chain_id); - + // Get the Ethereum address let address = wallet.address(); - + Ok(EthereumWallet { address, wallet, network, }) } - + /// Gets the Ethereum address as a string. pub fn address_string(&self) -> String { format!("{:?}", self.address) } - + /// Signs a message with the Ethereum wallet. pub async fn sign_message(&self, message: &[u8]) -> Result { - let signature = self.wallet.sign_message(message) + let signature = self + .wallet + .sign_message(message) .await .map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?; - + Ok(signature.to_string()) } - + /// Gets the private key as a hex string. pub fn private_key_hex(&self) -> String { let bytes = self.wallet.signer().to_bytes(); diff --git a/src/vault/keyspace/keypair_types.rs b/src/vault/keyspace/keypair_types.rs index 5dc174b..4f3fe1c 100644 --- a/src/vault/keyspace/keypair_types.rs +++ b/src/vault/keyspace/keypair_types.rs @@ -1,14 +1,16 @@ -/// Implementation of keypair functionality. - -use k256::ecdsa::{SigningKey, VerifyingKey, signature::{Signer, Verifier}, Signature}; use k256::ecdh::EphemeralSecret; +/// Implementation of keypair functionality. +use k256::ecdsa::{ + signature::{Signer, Verifier}, + Signature, SigningKey, VerifyingKey, +}; use rand::rngs::OsRng; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; use std::collections::HashMap; -use sha2::{Sha256, Digest}; -use crate::vault::symmetric::implementation; use crate::vault::error::CryptoError; +use crate::vault::symmetric::implementation; /// A keypair for signing and verifying messages. #[derive(Debug, Clone, Serialize, Deserialize)] @@ -23,8 +25,8 @@ pub struct KeyPair { // Serialization helpers for VerifyingKey mod verifying_key_serde { use super::*; - use serde::{Serializer, Deserializer}; use serde::de::{self, Visitor}; + use serde::{Deserializer, Serializer}; use std::fmt; pub fn serialize(key: &VerifyingKey, serializer: S) -> Result @@ -64,7 +66,7 @@ mod verifying_key_serde { while let Some(byte) = seq.next_element()? { bytes.push(byte); } - + VerifyingKey::from_sec1_bytes(&bytes).map_err(|e| { log::error!("Error deserializing verifying key from seq: {:?}", e); de::Error::custom(format!("invalid verifying key from seq: {:?}", e)) @@ -84,8 +86,8 @@ mod verifying_key_serde { // Serialization helpers for SigningKey mod signing_key_serde { use super::*; - use serde::{Serializer, Deserializer}; use serde::de::{self, Visitor}; + use serde::{Deserializer, Serializer}; use std::fmt; pub fn serialize(key: &SigningKey, serializer: S) -> Result @@ -125,7 +127,7 @@ mod signing_key_serde { while let Some(byte) = seq.next_element()? { bytes.push(byte); } - + SigningKey::from_bytes(bytes.as_slice().into()).map_err(|e| { log::error!("Error deserializing signing key from seq: {:?}", e); de::Error::custom(format!("invalid signing key from seq: {:?}", e)) @@ -147,7 +149,7 @@ impl KeyPair { pub fn new(name: &str) -> Self { let signing_key = SigningKey::random(&mut OsRng); let verifying_key = VerifyingKey::from(&signing_key); - + KeyPair { name: name.to_string(), verifying_key, @@ -159,7 +161,7 @@ impl KeyPair { pub fn pub_key(&self) -> Vec { self.verifying_key.to_sec1_bytes().to_vec() } - + /// Derives a public key from a private key. pub fn pub_key_from_private(private_key: &[u8]) -> Result, CryptoError> { let signing_key = SigningKey::from_bytes(private_key.into()) @@ -178,27 +180,31 @@ impl KeyPair { pub fn verify(&self, message: &[u8], signature_bytes: &[u8]) -> Result { let signature = Signature::from_bytes(signature_bytes.into()) .map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?; - + match self.verifying_key.verify(message, &signature) { Ok(_) => Ok(true), Err(_) => Ok(false), // Verification failed, but operation was successful } } - + /// Verifies a message signature using only a public key. - pub fn verify_with_public_key(public_key: &[u8], message: &[u8], signature_bytes: &[u8]) -> Result { - let verifying_key = VerifyingKey::from_sec1_bytes(public_key) - .map_err(|_| CryptoError::InvalidKeyLength)?; - + pub fn verify_with_public_key( + public_key: &[u8], + message: &[u8], + signature_bytes: &[u8], + ) -> Result { + let verifying_key = + VerifyingKey::from_sec1_bytes(public_key).map_err(|_| CryptoError::InvalidKeyLength)?; + let signature = Signature::from_bytes(signature_bytes.into()) .map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?; - + match verifying_key.verify(message, &signature) { Ok(_) => Ok(true), Err(_) => Ok(false), // Verification failed, but operation was successful } } - + /// Encrypts a message using the recipient's public key. /// This implements ECIES (Elliptic Curve Integrated Encryption Scheme): /// 1. Generate an ephemeral keypair @@ -206,19 +212,23 @@ impl KeyPair { /// 3. Derive encryption key from the shared secret /// 4. Encrypt the message using symmetric encryption /// 5. Return the ephemeral public key and the ciphertext - pub fn encrypt_asymmetric(&self, recipient_public_key: &[u8], message: &[u8]) -> Result, CryptoError> { + pub fn encrypt_asymmetric( + &self, + recipient_public_key: &[u8], + message: &[u8], + ) -> Result, CryptoError> { // Parse recipient's public key let recipient_key = VerifyingKey::from_sec1_bytes(recipient_public_key) .map_err(|_| CryptoError::InvalidKeyLength)?; - + // Generate ephemeral keypair let ephemeral_signing_key = SigningKey::random(&mut OsRng); let ephemeral_public_key = VerifyingKey::from(&ephemeral_signing_key); - + // Derive shared secret using ECDH let ephemeral_secret = EphemeralSecret::random(&mut OsRng); - let shared_secret = ephemeral_secret.diffie_hellman(&recipient_key.to_public_key()); - + let shared_secret = ephemeral_secret.diffie_hellman(&recipient_key.into()); + // Derive encryption key from the shared secret (e.g., using HKDF or hashing) // For simplicity, we'll hash the shared secret here let encryption_key = { @@ -226,46 +236,51 @@ impl KeyPair { hasher.update(shared_secret.raw_secret_bytes()); hasher.finalize().to_vec() }; - + // Encrypt the message using the derived key let ciphertext = implementation::encrypt_with_key(&encryption_key, message) .map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?; - + // Format: ephemeral_public_key || ciphertext - let mut result = ephemeral_public_key.to_encoded_point(false).as_bytes().to_vec(); + let mut result = ephemeral_public_key + .to_encoded_point(false) + .as_bytes() + .to_vec(); result.extend_from_slice(&ciphertext); - + Ok(result) } - + /// Decrypts a message using the recipient's private key. /// This is the counterpart to encrypt_asymmetric. pub fn decrypt_asymmetric(&self, ciphertext: &[u8]) -> Result, CryptoError> { // The first 33 or 65 bytes (depending on compression) are the ephemeral public key // For simplicity, we'll assume uncompressed keys (65 bytes) if ciphertext.len() <= 65 { - return Err(CryptoError::DecryptionFailed("Ciphertext too short".to_string())); + return Err(CryptoError::DecryptionFailed( + "Ciphertext too short".to_string(), + )); } - + // Extract ephemeral public key and actual ciphertext let ephemeral_public_key = &ciphertext[..65]; let actual_ciphertext = &ciphertext[65..]; - + // Parse ephemeral public key let sender_key = VerifyingKey::from_sec1_bytes(ephemeral_public_key) .map_err(|_| CryptoError::InvalidKeyLength)?; - + // Derive shared secret using ECDH let recipient_secret = EphemeralSecret::random(&mut OsRng); - let shared_secret = recipient_secret.diffie_hellman(&sender_key.to_public_key()); - + let shared_secret = recipient_secret.diffie_hellman(&sender_key.into()); + // Derive decryption key from the shared secret (using the same method as encryption) let decryption_key = { let mut hasher = Sha256::default(); hasher.update(shared_secret.raw_secret_bytes()); hasher.finalize().to_vec() }; - + // Decrypt the message using the derived key implementation::decrypt_with_key(&decryption_key, actual_ciphertext) .map_err(|e| CryptoError::DecryptionFailed(e.to_string())) @@ -293,7 +308,7 @@ impl KeySpace { if self.keypairs.contains_key(name) { return Err(CryptoError::KeypairAlreadyExists(name.to_string())); } - + let keypair = KeyPair::new(name); self.keypairs.insert(name.to_string(), keypair); Ok(()) @@ -301,7 +316,9 @@ impl KeySpace { /// Gets a keypair by name. pub fn get_keypair(&self, name: &str) -> Result<&KeyPair, CryptoError> { - self.keypairs.get(name).ok_or(CryptoError::KeypairNotFound(name.to_string())) + self.keypairs + .get(name) + .ok_or(CryptoError::KeypairNotFound(name.to_string())) } /// Lists all keypair names in the space. @@ -309,4 +326,3 @@ impl KeySpace { self.keypairs.keys().cloned().collect() } } - diff --git a/src/vault/kvs/store.rs b/src/vault/kvs/store.rs index f30ab85..74c9c6f 100644 --- a/src/vault/kvs/store.rs +++ b/src/vault/kvs/store.rs @@ -355,7 +355,7 @@ impl KvStore { // Save to disk self.save()?; - Ok(()) + Ok(()) } /// Gets the name of the store.