- 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.
272 lines
9.0 KiB
Markdown
272 lines
9.0 KiB
Markdown
# 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.
|
|
|
|
```rust
|
|
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.
|
|
|
|
```rust
|
|
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:
|
|
|
|
```rust
|
|
// 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:
|
|
|
|
```rust
|
|
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:
|
|
|
|
```rust
|
|
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:
|
|
|
|
```rust
|
|
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
|
|
- 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 length
|
|
- `SignatureFormatError` - Signature format error
|
|
- `KeypairAlreadyExists` - Keypair already exists
|
|
- `KeypairNotFound` - Keypair not found
|
|
- `NoActiveSpace` - No active key space
|
|
- `NoKeypairSelected` - No keypair selected
|
|
- `SerializationError` - 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 signing
|
|
- `advanced_example.rhai` - Advanced example with error handling
|
|
- `key_persistence_example.rhai` - Demonstrates creating and saving a key space to disk
|
|
- `load_existing_space.rhai` - Shows how to load a previously created key space
|