- Renamed examples directory to `_archive` to reflect legacy status. - Updated README.md to reflect current status of vault module, including migration from Sameh's implementation to Lee's. - Temporarily disabled Rhai scripting integration for the vault. - Added notes regarding current and future development steps.
9.0 KiB
Hero Vault Keypair Module
The Keypair module provides functionality for creating, managing, and using ECDSA keypairs for digital signatures and other cryptographic operations.
Module Structure
The Keypair module is organized into:
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
KeyPair
The KeyPair
type represents an ECDSA keypair used for digital signatures and other cryptographic operations.
pub struct KeyPair {
// Private fields
// ...
}
impl KeyPair {
// Create a new random keypair
pub fn new() -> Result<Self, CryptoError>;
// Create a keypair from an existing private key
pub fn from_private_key(private_key: &[u8]) -> Result<Self, CryptoError>;
// Get the public key
pub fn public_key(&self) -> &[u8];
// Sign a message
pub fn sign(&self, message: &[u8]) -> Result<Vec<u8>, CryptoError>;
// Verify a signature
pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool, CryptoError>;
// Derive an Ethereum address from the public key
pub fn to_ethereum_address(&self) -> Result<String, CryptoError>;
// Export the private key (should be used with caution)
pub fn export_private_key(&self) -> Result<Vec<u8>, CryptoError>;
}
KeySpace
The KeySpace
type represents a secure container for multiple keypairs, which can be encrypted and stored on disk.
pub struct KeySpace {
// Private fields
// ...
}
impl KeySpace {
// Create a new key space
pub fn new(name: &str, password: &str) -> Result<Self, CryptoError>;
// Load a key space from disk
pub fn load(name: &str, password: &str) -> Result<Self, CryptoError>;
// Save the key space to disk
pub fn save(&self) -> Result<(), CryptoError>;
// Create a new keypair in the key space
pub fn create_keypair(&mut self, name: &str, password: &str) -> Result<&KeyPair, CryptoError>;
// Select a keypair for use
pub fn select_keypair(&mut self, name: &str) -> Result<&KeyPair, CryptoError>;
// Get the currently selected keypair
pub fn current_keypair(&self) -> Result<&KeyPair, CryptoError>;
// List all keypairs in the key space
pub fn list_keypairs(&self) -> Result<Vec<String>, CryptoError>;
// Get a keypair by name
pub fn get_keypair(&self, name: &str) -> Result<&KeyPair, CryptoError>;
// Remove a keypair from the key space
pub fn remove_keypair(&mut self, name: &str) -> Result<(), CryptoError>;
// Rename a keypair
pub fn rename_keypair(&mut self, old_name: &str, new_name: &str) -> Result<(), CryptoError>;
// Get the name of the key space
pub fn name(&self) -> &str;
}
Key Features
Key Space Management
The module provides functionality for creating, loading, and managing key spaces:
// Create a new key space
let mut space = KeySpace::new("my_space", "secure_password")?;
// Save the key space to disk
space.save()?;
// Load a key space from disk
let mut loaded_space = KeySpace::load("my_space", "secure_password")?;
Keypair Management
The module provides functionality for creating, selecting, and using keypairs:
use crate::vault::keypair::{KeySpace, KeyPair};
use crate::vault::error::CryptoError; // Assuming CryptoError is in vault::error
fn demonstrate_keypair_management() -> Result<(), CryptoError> {
// Create a new key space
let mut space = KeySpace::new("my_space", "secure_password")?;
// 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>());
// 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>());
// List all keypairs in the key space
let keypairs = space.list_keypairs()?;
println!("Keypairs in space: {:?}", keypairs);
// 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")?;
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
The module provides functionality for signing and verifying messages using ECDSA:
use crate::vault::keypair::KeySpace;
use crate::vault::error::CryptoError; // Assuming CryptoError is in vault::error
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
The module provides functionality for deriving Ethereum addresses from keypairs:
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:
[dependencies]
hero_vault = "0.1.0" # Replace with the actual version
Then, you can import and use the module in your Rust code:
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:
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
- Private keys are never stored in plaintext
- The module uses secure random number generation for key creation
- All cryptographic operations use well-established libraries and algorithms
Error Handling
The module uses the CryptoError
type for handling errors that can occur during keypair operations:
InvalidKeyLength
- Invalid key lengthSignatureFormatError
- Signature format errorKeypairAlreadyExists
- Keypair already existsKeypairNotFound
- Keypair not foundNoActiveSpace
- No active key spaceNoKeypairSelected
- No keypair selectedSerializationError
- Serialization error
Examples
For examples of how to use the Keypair module, see the examples/hero_vault
directory, particularly:
example.rhai
- Basic example demonstrating key management and signingadvanced_example.rhai
- Advanced example with error handlingkey_persistence_example.rhai
- Demonstrates creating and saving a key space to diskload_existing_space.rhai
- Shows how to load a previously created key space