Snippet 4: Create User Locked Vault
#![allow(unused)] fn main() { pub fn initialize_for_user(&mut self, user_id: &str, password: &str) -> Result<()> { println!("Starting crypto initialization for user: {}", user_id); let start_time = std::time::Instant::now(); // Create user-specific config directory let mut user_config_path = self.config_path.clone(); user_config_path.push("users"); user_config_path.push(user_id); if !user_config_path.exists() { fs::create_dir_all(&user_config_path)?; } let key_file = user_config_path.join("auth.hash"); let metadata_file = user_config_path.join("security.meta"); let key = if key_file.exists() && metadata_file.exists() { println!("Loading existing user configuration..."); // Load existing setup let stored_hash = fs::read_to_string(&key_file)?; let parsed_hash = PasswordHash::new(&stored_hash) .map_err(|e| anyhow!("Failed to parse password hash: {}", e))?; println!("Verifying password..."); // Verify password (this should be fast with default Argon2) Argon2::default() .verify_password(password.as_bytes(), &parsed_hash) .map_err(|e| anyhow!("Password verification failed: {}", e))?; println!("Loading metadata..."); // Load metadata let metadata_content = fs::read_to_string(&metadata_file)?; let mut metadata: SecurityMetadata = serde_json::from_str(&metadata_content) .map_err(|e| anyhow!("Failed to parse security metadata: {}", e))?; // Handle backward compatibility - if hardware_components is empty, regenerate it if metadata.hardware_components.is_empty() { println!("Upgrading old metadata format..."); let (current_hash, current_components) = self.generate_stable_hardware_fingerprint()?; // Update the metadata with current components metadata.hardware_components = current_components; metadata.hardware_fingerprint_hash = current_hash; // Save updated metadata fs::write(&metadata_file, serde_json::to_string_pretty(&metadata)?)?; println!("Metadata upgraded successfully"); } else { println!("Checking hardware fingerprint..."); // Get current hardware components let (current_hash, current_components) = self.generate_stable_hardware_fingerprint()?; // Check if hardware fingerprint matches if metadata.hardware_fingerprint_hash != current_hash { // Try to identify what changed let mut changed_components = Vec::new(); for (i, (stored, current)) in metadata .hardware_components .iter() .zip(current_components.iter()) .enumerate() { if stored != current { changed_components .push(format!("Component {}: '{}' -> '{}'", i, stored, current)); } } if !changed_components.is_empty() { println!("Hardware changes detected:"); for change in &changed_components { println!(" {}", change); } // For now, let's be more lenient and only fail if critical components changed if self.is_critical_hardware_change( &metadata.hardware_components, ¤t_components, ) { return Err(anyhow!( "Critical hardware components changed: {}", changed_components.join(", ") )); } else { println!("Non-critical hardware changes detected, allowing access..."); // Update the stored fingerprint metadata.hardware_fingerprint_hash = current_hash; metadata.hardware_components = current_components; // Save updated metadata fs::write(&metadata_file, serde_json::to_string_pretty(&metadata)?)?; } } } else { println!("Hardware fingerprint matches!"); } } self.security_metadata = Some(metadata); println!("Deriving encryption key..."); // Use standard security key derivation self.derive_secure_key(password) } else { println!("First time setup for user..."); let current_time = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); let (hardware_hash, hardware_components) = self.generate_stable_hardware_fingerprint()?; println!("Initial hardware components: {:?}", hardware_components); println!("Initial hardware hash: {}", hardware_hash); let metadata = SecurityMetadata { version: 1, created_timestamp: current_time, hardware_fingerprint_hash: hardware_hash, hardware_components, }; let key = self.derive_secure_key(password); println!("Storing password hash..."); // Store password hash let verification_salt = SaltString::generate(&mut OsRng); let argon2 = Argon2::default(); let password_hash = argon2 .hash_password(password.as_bytes(), &verification_salt) .map_err(|e| anyhow!("Failed to hash password: {}", e))?; fs::write(&key_file, password_hash.to_string())?; fs::write(&metadata_file, serde_json::to_string_pretty(&metadata)?)?; self.secure_file_permissions(&key_file)?; self.secure_file_permissions(&metadata_file)?; self.security_metadata = Some(metadata); key }; self.cipher = Some(ChaCha20Poly1305::new(&key)); let elapsed = start_time.elapsed(); println!( "Crypto initialization completed in {:.2}s", elapsed.as_secs_f64() ); Ok(()) } }
Advanced Cryptographic User Vault System with Hardware Binding
This sophisticated function represents the heart of the application's security architecture, implementing a comprehensive user-specific cryptographic vault system. It combines multiple layers of security including password-based authentication, hardware fingerprinting, and modern encryption algorithms to create a robust, tamper-resistant storage system.
Comprehensive Security Architecture Analysis
Function Signature and Purpose:
#![allow(unused)] fn main() { pub fn initialize_for_user(&mut self, user_id: &str, password: &str) -> Result<()> }
This function serves as the central security initialization point, responsible for establishing or restoring a user's complete cryptographic environment. It handles both first-time user setup and subsequent authentication sessions with equal security rigor.
Performance Monitoring and Logging: The function begins with comprehensive logging and performance tracking:
- Detailed Logging: Provides extensive debug information for security auditing and troubleshooting
- Performance Timing: Tracks initialization duration to identify potential performance issues or security attacks
- User Context: Logs the specific user ID for audit trail purposes
User-Specific Directory Architecture:
#![allow(unused)] fn main() { let mut user_config_path = self.config_path.clone(); user_config_path.push("users"); user_config_path.push(user_id); }
The system creates a hierarchical directory structure that provides:
- User Isolation: Each user has completely separate storage, preventing data leakage between accounts
- Organized Storage: Clear directory structure makes system administration and backup easier
- Scalability: Can handle unlimited users without naming conflicts or performance degradation
- Security Boundaries: File system permissions can be applied at the user level
Critical Security Files Management: Two essential files store the user's security credentials:
auth.hash
: Contains the Argon2 password hash for authenticationsecurity.meta
: Stores hardware fingerprinting data and security metadata
Existing User Authentication Flow: For returning users, the system performs a multi-step verification process:
Password Hash Verification:
#![allow(unused)] fn main() { let stored_hash = fs::read_to_string(&key_file)?; let parsed_hash = PasswordHash::new(&stored_hash)?; Argon2::default().verify_password(password.as_bytes(), &parsed_hash)?; }
This implements industry-standard password verification:
- Argon2 Algorithm: Uses the winner of the Password Hashing Competition, resistant to both GPU and ASIC attacks
- Salt Integration: Each password hash includes a unique salt to prevent rainbow table attacks
- Constant-Time Verification: Prevents timing attacks that could leak password information
- Memory-Hard Function: Requires significant memory allocation, making brute force attacks expensive
Hardware Fingerprinting System: The system implements sophisticated hardware binding to prevent credential theft:
Backward Compatibility Handling:
#![allow(unused)] fn main() { if metadata.hardware_components.is_empty() { println!("Upgrading old metadata format..."); let (current_hash, current_components) = self.generate_stable_hardware_fingerprint()?; metadata.hardware_components = current_components; metadata.hardware_fingerprint_hash = current_hash; } }
This graceful upgrade system:
- Seamless Migration: Automatically upgrades older installations without user intervention
- Data Preservation: Maintains existing user data while adding new security features
- Future-Proofing: Establishes a pattern for future security enhancements
Hardware Change Detection:
#![allow(unused)] fn main() { if metadata.hardware_fingerprint_hash != current_hash { let mut changed_components = Vec::new(); for (i, (stored, current)) in metadata.hardware_components.iter().zip(current_components.iter()).enumerate() { if stored != current { changed_components.push(format!("Component {}: '{}' -> '{}'", i, stored, current)); } } } }
The system provides intelligent hardware change handling:
- Component-Level Analysis: Identifies exactly which hardware components have changed
- Detailed Logging: Records specific changes for security auditing
- Flexible Response: Distinguishes between critical and non-critical hardware changes
- User Transparency: Provides clear information about detected changes
Critical vs Non-Critical Hardware Changes: The system implements a nuanced approach to hardware changes:
- Critical Changes: Major components like CPU or motherboard that indicate potential system compromise
- Non-Critical Changes: Minor changes like RAM upgrades or peripheral additions
- Adaptive Security: Updates fingerprints for non-critical changes while blocking critical ones
First-Time User Setup: For new users, the system performs comprehensive initialization:
Security Metadata Creation:
#![allow(unused)] fn main() { let metadata = SecurityMetadata { version: 1, created_timestamp: current_time, hardware_fingerprint_hash: hardware_hash, hardware_components, }; }
This metadata provides:
- Version Tracking: Enables future security upgrades and compatibility handling
- Timestamp Recording: Creates audit trail for account creation
- Hardware Binding: Establishes the baseline hardware configuration
- Component Inventory: Detailed record of hardware components for change detection
Secure Key Derivation:
The system uses the derive_secure_key()
method to generate encryption keys:
- Password-Based Key Derivation: Uses the user's password as the primary key material
- Cryptographically Secure: Employs proven key derivation functions
- Unique Per User: Each user gets completely unique encryption keys
- Memory Protection: Keys are handled securely in memory
Password Hash Storage:
#![allow(unused)] fn main() { let verification_salt = SaltString::generate(&mut OsRng); let argon2 = Argon2::default(); let password_hash = argon2.hash_password(password.as_bytes(), &verification_salt)?; }
The password storage system implements best practices:
- Cryptographically Secure Random Salt: Uses OS-provided randomness for salt generation
- Argon2 Default Parameters: Uses recommended parameters for security vs performance balance
- Secure Storage: Hash is immediately written to disk with secure permissions
File System Security:
#![allow(unused)] fn main() { self.secure_file_permissions(&key_file)?; self.secure_file_permissions(&metadata_file)?; }
The system applies strict file permissions:
- Owner-Only Access: Files are readable and writable only by the file owner
- No Group/Other Access: Prevents other users on the system from accessing sensitive data
- Cross-Platform Implementation: Handles permission setting across different operating systems
Cipher Initialization:
#![allow(unused)] fn main() { self.cipher = Some(ChaCha20Poly1305::new(&key)); }
The final step establishes the encryption system:
- ChaCha20Poly1305: Modern authenticated encryption algorithm
- Key Binding: Cipher is initialized with the user-specific derived key
- Ready State: System is now ready for encrypt/decrypt operations
Performance Optimization: The function concludes with performance reporting:
- Timing Analysis: Measures and reports total initialization time
- Performance Monitoring: Helps identify potential security attacks or system issues
- User Feedback: Provides transparency about system operations
Error Handling and Security: Throughout the function, comprehensive error handling ensures:
- Graceful Failure: All errors are properly propagated with descriptive messages
- Security Logging: Failed operations are logged for security monitoring
- State Consistency: Partial failures don't leave the system in an inconsistent state
- Attack Resistance: Error messages don't leak sensitive information
This snippet implements the core cryptographic initialization system for user-specific encrypted storage. The initialize_for_user()
function:
Security Setup:
- Creates user-specific directories: Establishes isolated storage for each user
- Manages encryption keys: Derives secure keys from user passwords using Argon2
- Hardware fingerprinting: Binds encryption to specific hardware to prevent unauthorized access
Key Operations:
- First-time setup: Generates new encryption keys and stores security metadata
- Existing user login: Verifies password and loads existing encryption configuration
- Hardware change detection: Identifies and handles hardware modifications gracefully
- Backward compatibility: Upgrades old metadata formats automatically
Security Features:
- Password verification: Uses cryptographically secure Argon2 hashing
- File permissions: Sets restrictive permissions on sensitive files (Unix systems)
- ChaCha20Poly1305 encryption: Initializes modern, secure cipher for data protection
This is the foundation of the application's security model, ensuring each user's data remains encrypted and tied to their specific device.