tests & fixes in kvs & keypair
This commit is contained in:
parent
3a0900fc15
commit
3f8aecb786
@ -21,7 +21,7 @@ env_logger = "0.10.0" # Logger implementation
|
||||
ethers = { version = "2.0.7", features = ["legacy"] } # Ethereum library
|
||||
glob = "0.3.1" # For file pattern matching
|
||||
jsonrpsee = "0.25.1"
|
||||
k256 = { version = "0.13.1", features = ["ecdsa"] } # Elliptic curve cryptography
|
||||
k256 = { version = "0.13.1", features = ["ecdsa", "ecdh"] } # Elliptic curve cryptography
|
||||
lazy_static = "1.4.0" # For lazy initialization of static variables
|
||||
libc = "0.2"
|
||||
log = "0.4" # Logging facade
|
||||
|
@ -214,18 +214,16 @@ impl KeyPair {
|
||||
let ephemeral_signing_key = SigningKey::random(&mut OsRng);
|
||||
let ephemeral_public_key = VerifyingKey::from(&ephemeral_signing_key);
|
||||
|
||||
// Derive shared secret (this is a simplified ECDH)
|
||||
// In a real implementation, we would use proper ECDH, but for this example:
|
||||
let shared_point = recipient_key.to_encoded_point(false);
|
||||
let shared_secret = {
|
||||
let mut hasher = Sha256::default();
|
||||
hasher.update(ephemeral_signing_key.to_bytes());
|
||||
hasher.update(shared_point.as_bytes());
|
||||
hasher.finalize().to_vec()
|
||||
};
|
||||
// Derive shared secret using ECDH
|
||||
let shared_secret_bytes = ephemeral_signing_key.diffie_hellman(&recipient_key);
|
||||
|
||||
// Derive encryption key from the shared secret (using a simple hash for this example)
|
||||
let mut hasher = Sha256::default();
|
||||
hasher.update(shared_secret_bytes.as_bytes());
|
||||
let encryption_key = hasher.finalize().to_vec();
|
||||
|
||||
// Encrypt the message using the derived key
|
||||
let ciphertext = implementation::encrypt_with_key(&shared_secret, message)
|
||||
let ciphertext = implementation::encrypt_with_key(&encryption_key, message)
|
||||
.map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?;
|
||||
|
||||
// Format: ephemeral_public_key || ciphertext
|
||||
@ -252,17 +250,16 @@ impl KeyPair {
|
||||
let sender_key = VerifyingKey::from_sec1_bytes(ephemeral_public_key)
|
||||
.map_err(|_| CryptoError::InvalidKeyLength)?;
|
||||
|
||||
// Derive shared secret (simplified ECDH)
|
||||
let shared_point = sender_key.to_encoded_point(false);
|
||||
let shared_secret = {
|
||||
let mut hasher = Sha256::default();
|
||||
hasher.update(self.signing_key.to_bytes());
|
||||
hasher.update(shared_point.as_bytes());
|
||||
hasher.finalize().to_vec()
|
||||
};
|
||||
// Derive shared secret using ECDH
|
||||
let shared_secret_bytes = self.signing_key.diffie_hellman(&sender_key);
|
||||
|
||||
// Derive encryption key from the shared secret (using the same simple hash)
|
||||
let mut hasher = Sha256::default();
|
||||
hasher.update(shared_secret_bytes.as_bytes());
|
||||
let encryption_key = hasher.finalize().to_vec();
|
||||
|
||||
// Decrypt the message using the derived key
|
||||
implementation::decrypt_with_key(&shared_secret, actual_ciphertext)
|
||||
implementation::decrypt_with_key(&encryption_key, actual_ciphertext)
|
||||
.map_err(|e| CryptoError::DecryptionFailed(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
@ -13,3 +13,6 @@ pub use session_manager::{
|
||||
keypair_pub_key, derive_public_key, keypair_sign, keypair_verify,
|
||||
verify_with_public_key, encrypt_asymmetric, decrypt_asymmetric
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
7
src/vault/keypair/tests/implementation_tests.rs
Normal file
7
src/vault/keypair/tests/implementation_tests.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
86
src/vault/keypair/tests/keypair_types_tests.rs
Normal file
86
src/vault/keypair/tests/keypair_types_tests.rs
Normal file
@ -0,0 +1,86 @@
|
||||
|
||||
use crate::vault::keypair::keypair_types::{KeyPair, KeySpace};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_keypair_creation() {
|
||||
let keypair = KeyPair::new("test_keypair");
|
||||
assert_eq!(keypair.name, "test_keypair");
|
||||
// Basic check that keys are generated (they should have non-zero length)
|
||||
assert!(!keypair.pub_key().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keypair_sign_and_verify() {
|
||||
let keypair = KeyPair::new("test_keypair");
|
||||
let message = b"This is a test message";
|
||||
let signature = keypair.sign(message);
|
||||
assert!(!signature.is_empty());
|
||||
|
||||
let is_valid = keypair.verify(message, &signature).expect("Verification failed");
|
||||
assert!(is_valid);
|
||||
|
||||
// Test with a wrong message
|
||||
let wrong_message = b"This is a different message";
|
||||
let is_valid_wrong = keypair.verify(wrong_message, &signature).expect("Verification failed with wrong message");
|
||||
assert!(!is_valid_wrong);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_with_public_key() {
|
||||
let keypair = KeyPair::new("test_keypair");
|
||||
let message = b"Another test message";
|
||||
let signature = keypair.sign(message);
|
||||
let public_key = keypair.pub_key();
|
||||
|
||||
let is_valid = KeyPair::verify_with_public_key(&public_key, message, &signature).expect("Verification with public key failed");
|
||||
assert!(is_valid);
|
||||
|
||||
// Test with a wrong public key
|
||||
let wrong_keypair = KeyPair::new("wrong_keypair");
|
||||
let wrong_public_key = wrong_keypair.pub_key();
|
||||
let is_valid_wrong_key = KeyPair::verify_with_public_key(&wrong_public_key, message, &signature).expect("Verification with wrong public key failed");
|
||||
assert!(!is_valid_wrong_key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_asymmetric_encryption_decryption() {
|
||||
// Sender's keypair
|
||||
let sender_keypair = KeyPair::new("sender");
|
||||
let sender_public_key = sender_keypair.pub_key();
|
||||
|
||||
// Recipient's keypair
|
||||
let recipient_keypair = KeyPair::new("recipient");
|
||||
let recipient_public_key = recipient_keypair.pub_key();
|
||||
|
||||
let message = b"This is a secret message";
|
||||
|
||||
// Sender encrypts for recipient
|
||||
let ciphertext = sender_keypair.encrypt_asymmetric(&recipient_public_key, message).expect("Encryption failed");
|
||||
assert!(!ciphertext.is_empty());
|
||||
|
||||
// Recipient decrypts
|
||||
let decrypted_message = recipient_keypair.decrypt_asymmetric(&ciphertext).expect("Decryption failed");
|
||||
assert_eq!(decrypted_message, message);
|
||||
|
||||
// Test decryption with wrong keypair
|
||||
let wrong_keypair = KeyPair::new("wrong_recipient");
|
||||
let result = wrong_keypair.decrypt_asymmetric(&ciphertext);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyspace_add_keypair() {
|
||||
let mut space = KeySpace::new("test_space");
|
||||
space.add_keypair("keypair1").expect("Failed to add keypair1");
|
||||
assert_eq!(space.keypairs.len(), 1);
|
||||
assert!(space.keypairs.contains_key("keypair1"));
|
||||
|
||||
// Test adding a duplicate keypair
|
||||
let result = space.add_keypair("keypair1");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
3
src/vault/keypair/tests/mod.rs
Normal file
3
src/vault/keypair/tests/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod implementation_tests;
|
||||
mod keypair_types_tests;
|
||||
mod session_manager_tests;
|
111
src/vault/keypair/tests/session_manager_tests.rs
Normal file
111
src/vault/keypair/tests/session_manager_tests.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use crate::vault::keypair::session_manager::{
|
||||
clear_session, create_keypair, create_space, get_current_space, get_selected_keypair,
|
||||
list_keypairs, select_keypair, set_current_space, SESSION,
|
||||
};
|
||||
use crate::vault::keypair::keypair_types::KeySpace;
|
||||
|
||||
// Helper function to clear the session before each test
|
||||
fn setup_test() {
|
||||
clear_session();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_create_and_get_space() {
|
||||
setup_test();
|
||||
create_space("test_space").expect("Failed to create space");
|
||||
let space = get_current_space().expect("Failed to get current space");
|
||||
assert_eq!(space.name, "test_space");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_current_space() {
|
||||
setup_test();
|
||||
let space = KeySpace::new("another_space");
|
||||
set_current_space(space.clone()).expect("Failed to set current space");
|
||||
let current_space = get_current_space().expect("Failed to get current space");
|
||||
assert_eq!(current_space.name, "another_space");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clear_session() {
|
||||
setup_test();
|
||||
create_space("test_space").expect("Failed to create space");
|
||||
clear_session();
|
||||
let result = get_current_space();
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_and_select_keypair() {
|
||||
setup_test();
|
||||
create_space("test_space").expect("Failed to create space");
|
||||
create_keypair("test_keypair").expect("Failed to create keypair");
|
||||
let keypair = get_selected_keypair().expect("Failed to get selected keypair");
|
||||
assert_eq!(keypair.name, "test_keypair");
|
||||
|
||||
select_keypair("test_keypair").expect("Failed to select keypair");
|
||||
let selected_keypair = get_selected_keypair().expect("Failed to get selected keypair after select");
|
||||
assert_eq!(selected_keypair.name, "test_keypair");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_keypairs() {
|
||||
setup_test();
|
||||
create_space("test_space").expect("Failed to create space");
|
||||
create_keypair("keypair1").expect("Failed to create keypair1");
|
||||
create_keypair("keypair2").expect("Failed to create keypair2");
|
||||
|
||||
let keypairs = list_keypairs().expect("Failed to list keypairs");
|
||||
assert_eq!(keypairs.len(), 2);
|
||||
assert!(keypairs.contains(&"keypair1".to_string()));
|
||||
assert!(keypairs.contains(&"keypair2".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_keypair_no_active_space() {
|
||||
setup_test();
|
||||
let result = create_keypair("test_keypair");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_select_keypair_no_active_space() {
|
||||
setup_test();
|
||||
let result = select_keypair("test_keypair");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_select_nonexistent_keypair() {
|
||||
setup_test();
|
||||
create_space("test_space").expect("Failed to create space");
|
||||
let result = select_keypair("nonexistent_keypair");
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_selected_keypair_no_active_space() {
|
||||
setup_test();
|
||||
let result = get_selected_keypair();
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_selected_keypair_no_keypair_selected() {
|
||||
setup_test();
|
||||
create_space("test_space").expect("Failed to create space");
|
||||
let result = get_selected_keypair();
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_keypairs_no_active_space() {
|
||||
setup_test();
|
||||
let result = list_keypairs();
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
@ -165,3 +165,9 @@ let loaded_store = KvStore::load("my_store", "secure_password")?;
|
||||
let api_key = loaded_store.get("api_key")?;
|
||||
println!("API Key: {}", api_key.unwrap_or_default());
|
||||
```
|
||||
|
||||
## to test
|
||||
|
||||
```bash
|
||||
cargo test --lib vault::keypair
|
||||
```
|
@ -12,3 +12,6 @@ pub use store::{
|
||||
create_store, open_store, delete_store,
|
||||
list_stores, get_store_path
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -355,7 +355,7 @@ impl KvStore {
|
||||
// Save to disk
|
||||
self.save()?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the name of the store.
|
||||
|
1
src/vault/kvs/tests/mod.rs
Normal file
1
src/vault/kvs/tests/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
mod store_tests;
|
105
src/vault/kvs/tests/store_tests.rs
Normal file
105
src/vault/kvs/tests/store_tests.rs
Normal file
@ -0,0 +1,105 @@
|
||||
use crate::vault::kvs::store::{create_store, delete_store, open_store, KvStore};
|
||||
use std::path::PathBuf;
|
||||
|
||||
// Helper function to generate a unique store name for each test
|
||||
fn generate_test_store_name() -> String {
|
||||
use rand::Rng;
|
||||
let random_string: String = rand::thread_rng()
|
||||
.sample_iter(&rand::distributions::Alphanumeric)
|
||||
.take(10)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
format!("test_store_{}", random_string)
|
||||
}
|
||||
|
||||
// Helper function to clean up test stores
|
||||
fn cleanup_test_store(name: &str) {
|
||||
let _ = delete_store(name);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_create_and_open_store() {
|
||||
let store_name = generate_test_store_name();
|
||||
let store = create_store(&store_name, false, None).expect("Failed to create store");
|
||||
assert_eq!(store.name(), store_name);
|
||||
assert!(!store.is_encrypted());
|
||||
|
||||
let opened_store = open_store(&store_name, None).expect("Failed to open store");
|
||||
assert_eq!(opened_store.name(), store_name);
|
||||
assert!(!opened_store.is_encrypted());
|
||||
|
||||
cleanup_test_store(&store_name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_and_get_value() {
|
||||
let store_name = generate_test_store_name();
|
||||
let store = create_store(&store_name, false, None).expect("Failed to create store");
|
||||
|
||||
store.set("key1", &"value1").expect("Failed to set value");
|
||||
let value: String = store.get("key1").expect("Failed to get value");
|
||||
assert_eq!(value, "value1");
|
||||
|
||||
cleanup_test_store(&store_name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_value() {
|
||||
let store_name = generate_test_store_name();
|
||||
let store = create_store(&store_name, false, None).expect("Failed to create store");
|
||||
|
||||
store.set("key1", &"value1").expect("Failed to set value");
|
||||
store.delete("key1").expect("Failed to delete value");
|
||||
let result: Result<String, _> = store.get("key1");
|
||||
assert!(result.is_err());
|
||||
|
||||
cleanup_test_store(&store_name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains_key() {
|
||||
let store_name = generate_test_store_name();
|
||||
let store = create_store(&store_name, false, None).expect("Failed to create store");
|
||||
|
||||
store.set("key1", &"value1").expect("Failed to set value");
|
||||
assert!(store.contains("key1").expect("Failed to check contains"));
|
||||
assert!(!store.contains("key2").expect("Failed to check contains"));
|
||||
|
||||
cleanup_test_store(&store_name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_keys() {
|
||||
let store_name = generate_test_store_name();
|
||||
let store = create_store(&store_name, false, None).expect("Failed to create store");
|
||||
|
||||
store.set("key1", &"value1").expect("Failed to set value");
|
||||
store.set("key2", &"value2").expect("Failed to set value");
|
||||
|
||||
let keys = store.keys().expect("Failed to list keys");
|
||||
assert_eq!(keys.len(), 2);
|
||||
assert!(keys.contains(&"key1".to_string()));
|
||||
assert!(keys.contains(&"key2".to_string()));
|
||||
|
||||
cleanup_test_store(&store_name);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clear_store() {
|
||||
let store_name = generate_test_store_name();
|
||||
let store = create_store(&store_name, false, None).expect("Failed to create store");
|
||||
|
||||
store.set("key1", &"value1").expect("Failed to set value");
|
||||
store.set("key2", &"value2").expect("Failed to set value");
|
||||
|
||||
store.clear().expect("Failed to clear store");
|
||||
let keys = store.keys().expect("Failed to list keys after clear");
|
||||
assert!(keys.is_empty());
|
||||
|
||||
cleanup_test_store(&store_name);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user