# Sharenet Passport Creator Implementation Plan ## Overview A Rust command-line application for creating and managing Sharenet Passports - cryptographic identities for the Sharenet protocol. The tool generates secure identities that can be used to join nodes, sign Cards, and encrypt communications. ## Core Components ### 1. Passport Structure **Based on Sharenet Spec Sections 11, 27:** - 24-word recovery phrase (BIP-39) - Derived Ed25519 keypair for signing - DID constructed from public key - Encrypted export format (.spf files) - Cross-platform compatibility ### 2. Cryptographic Requirements **Algorithms (Spec Section 15):** - **Mnemonic**: BIP-39 with 256-bit entropy - **Key Derivation**: Ed25519 from seed - **File Encryption**: XChaCha20-Poly1305 - **Key Derivation**: HKDF-SHA256 - **Hashing**: SHA-256 **Rust Crates:** - `bip39` - BIP-39 mnemonic generation - `ed25519-dalek` - Ed25519 signatures - `chacha20poly1305` - XChaCha20-Poly1305 encryption - `hkdf` - HKDF key derivation - `sha2` - SHA-256 hashing - `rand` - CSPRNG for key generation - `serde_cbor` - CBOR serialization - `clap` - CLI argument parsing ### 3. File Format (.spf) **CBOR Structure (before encryption):** ```rust struct PassportFile { enc_seed: Vec, // seed encrypted under KEK kdf: String, // "HKDF-SHA256" cipher: String, // "XChaCha20-Poly1305" salt: Vec, // 32-byte salt for KEK derivation nonce: Vec, // 24-byte nonce for encryption public_key: Vec, // Ed25519 public key did: String, // Generated DID created_at: u64, // Creation timestamp version: String, // File format version } ``` **Storage:** - File extension: `.spf` (Sharenet Passport File) - Default location: `~/.sharenet/passports/` - Secure file permissions (600) ## CLI Interface ### Commands 1. **`create`** - Generate new Passport ```bash sharenet-passport create [--output FILE] [--security-level LEVEL] ``` 2. **`import-recovery`** - Import from recovery phrase ```bash sharenet-passport import-recovery [--output FILE] ``` 3. **`import-file`** - Import from .spf file ```bash sharenet-passport import-file [--security-level LEVEL] ``` 4. **`export`** - Export Passport to .spf file ```bash sharenet-passport export [--output FILE] ``` 5. **`info`** - Display Passport details ```bash sharenet-passport info [FILE] ``` 6. **`sign`** - Sign a message (testing) ```bash sharenet-passport sign ``` ### Security Levels Users can choose their preferred security/convenience trade-off: 1. **`maximum`** - Password required for every operation 2. **`session`** - Password on app start, keys in memory until close (default) 3. **`timeout=Xh`** - Password required every X hours 4. **`keychain`** - Password once, keys stored in system keychain (desktop only) ## Implementation Phases ### Phase 1: Core Cryptographic Library - [ ] BIP-39 mnemonic generation and validation - [ ] Ed25519 key derivation from seed - [ ] XChaCha20-Poly1305 encryption/decryption - [ ] HKDF key derivation - [ ] CBOR serialization/deserialization ### Phase 2: Passport Data Structures - [ ] Passport struct with recovery phrase, keys, DID - [ ] .spf file format implementation - [ ] File I/O operations with error handling - [ ] Memory zeroization for sensitive data ### Phase 3: CLI Implementation - [ ] Command parsing with clap - [ ] Secure password input (no echo) - [ ] File permission enforcement - [ ] User-friendly output formatting ### Phase 4: Security Features - [ ] Multiple security level implementations - [ ] System keychain integration (desktop) - [ ] Session management - [ ] Error handling and validation ### Phase 5: Testing & Documentation - [ ] Unit tests for cryptographic operations - [ ] Integration tests for CLI workflows - [ ] Security testing and audit - [ ] User documentation and examples ## Project Structure ``` sharenet-passport-cli/ ├── src/ │ ├── main.rs # CLI entry point │ ├── cli/ │ │ ├── mod.rs # Command definitions │ │ ├── create.rs # Create command │ │ ├── import.rs # Import commands │ │ └── export.rs # Export command │ ├── crypto/ │ │ ├── mod.rs # Cryptographic operations │ │ ├── bip39.rs # BIP-39 implementation │ │ ├── encryption.rs # File encryption │ │ └── keys.rs # Key generation │ ├── passport/ │ │ ├── mod.rs # Passport data structures │ │ ├── file_format.rs # .spf file handling │ │ └── did.rs # DID generation │ ├── storage/ │ │ ├── mod.rs # Storage abstractions │ │ ├── file_system.rs # File I/O │ │ └── keychain.rs # System keychain (desktop) │ └── error.rs # Error types ├── Cargo.toml ├── tests/ │ ├── unit/ │ └── integration/ └── docs/ └── implementation_plan.md ``` ## Security Considerations - Zeroize sensitive memory after use - Secure password input handling - File permission enforcement - Cryptographic randomness verification - Recovery phrase validation - Error handling without information leakage ## Testing Strategy **Unit Tests:** - Mnemonic generation and validation - Key derivation consistency - Encryption/decryption round-trip - File format serialization **Integration Tests:** - Full CLI workflow (create → export → import → sign) - Cross-platform file handling - Password recovery scenarios **Security Tests:** - Memory zeroization verification - File permission validation - Cryptographic randomness testing --- # .spf File Import and Usage in Applications *This section details how .spf files would be imported and used in various application types, beyond the scope of the Passport Creator CLI itself.* ## Web Applications ### Security Limitations - Cannot access system keychains or secure storage - Limited to browser storage (IndexedDB, localStorage) - Private keys stored in potentially extractable formats ### Implementation Options #### Option 1: Session-Based (Recommended) ```javascript // On app start async function loadPassport(spfFile, password) { const passport = await decryptSPF(spfFile, password); // Keep private key in memory only sessionStorage.setItem('passport_loaded', 'true'); return passport; } // On app close or browser refresh function cleanup() { // Clear keys from memory sessionStorage.removeItem('passport_loaded'); } ``` #### Option 2: Encrypted Browser Storage ```javascript // With user consent and security warning async function storePassport(spfFile, password, storagePassword) { const passport = await decryptSPF(spfFile, password); const encryptedKey = await encryptForStorage( passport.privateKey, storagePassword ); localStorage.setItem('encrypted_private_key', encryptedKey); } // Requires storage password on each use async function loadFromStorage(storagePassword) { const encrypted = localStorage.getItem('encrypted_private_key'); return await decryptFromStorage(encrypted, storagePassword); } ``` #### Option 3: Per-Operation Password ```javascript // Maximum security, maximum inconvenience async function signMessage(spfFile, password, message) { const passport = await decryptSPF(spfFile, password); const signature = await passport.sign(message); // Immediately clear from memory return signature; } ``` ### Web Security Trade-offs - **Session-based**: Good balance, but keys lost on browser close - **Encrypted storage**: Convenient but relies on user-chosen password strength - **Per-operation**: Most secure but poor user experience ## Native Mobile Applications ### Android Implementation #### Using Android Keystore ```kotlin class PassportManager { private val keyStore = KeyStore.getInstance("AndroidKeyStore") fun importSPF(spfFile: File, password: String) { // Decrypt .spf file val passport = decryptSPF(spfFile, password) // Generate new keypair in Android Keystore val keyPair = generateKeyPairInKeystore("sharenet_passport") // The private key never leaves secure hardware // Future operations use Keystore signing } fun signData(data: ByteArray): ByteArray { // Sign directly using Keystore return keyStore.getKey("sharenet_passport", null).sign(data) } } ``` #### Alternative: Encrypted SharedPreferences ```kotlin fun storeInEncryptedPrefs(passport: Passport, password: String) { val encryptedPrefs = EncryptedSharedPreferences.create( "sharenet_passport", MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) ) // Store encrypted private key encryptedPrefs.edit() .putString("encrypted_private_key", encryptKey(passport.privateKey, password)) .apply() } ``` ### iOS Implementation #### Using iOS Keychain ```swift class PassportManager { func importSPF(spfFile: URL, password: String) throws { // Decrypt .spf file let passport = try decryptSPF(spfFile, password: password) // Store private key in Keychain let query: [String: Any] = [ kSecClass as String: kSecClassKey, kSecAttrApplicationTag as String: "sharenet.passport.private", kSecValueRef as String: passport.privateKey, kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly ] SecItemAdd(query as CFDictionary, nil) } func signData(_ data: Data) throws -> Data { // Retrieve from Keychain and sign let privateKey = try retrievePrivateKey() return try privateKey.sign(data: data) } } ``` ## Desktop Applications ### Cross-Platform Secure Storage #### Using system keychains: - **macOS**: Keychain Services - **Linux**: libsecret / GNOME Keyring - **Windows**: Credential Manager #### Implementation Pattern: ```rust // After importing .spf file once fn store_in_keychain(passport: &Passport, password: &str) -> Result<()> { let encrypted_key = encrypt_for_storage(&passport.private_key, password)?; #[cfg(target_os = "macos")] keychain::macos::store("sharenet_passport", &encrypted_key)?; #[cfg(target_os = "linux")] keychain::linux::store("sharenet_passport", &encrypted_key)?; #[cfg(target_os = "windows")] keychain::windows::store("sharenet_passport", &encrypted_key)?; Ok(()) } ``` ## Password Decryption Scheme ### .spf File Decryption Process 1. **Read .spf file** and parse CBOR structure 2. **Derive KEK** from user password using HKDF: ``` KEK = HKDF-SHA256(salt, password, info="sharenet-passport-kek") ``` 3. **Decrypt seed** using XChaCha20-Poly1305: ``` seed = XChaCha20-Poly1305-Decrypt(KEK, nonce, enc_seed) ``` 4. **Regenerate keys** from seed using BIP-39 derivation 5. **Verify integrity** by comparing generated public key with stored public key ### Application-Specific Storage After initial .spf decryption, applications can choose their storage strategy: - **Web**: Keep in memory or encrypt with separate password for browser storage - **Mobile**: Store in platform secure storage (Keystore/Keychain) - **Desktop**: Store in system keychain or keep in memory ### Security Considerations for Each Platform - **Web**: Highest risk - recommend session-based or per-operation passwords - **Mobile**: Good security through platform mechanisms - **Desktop**: Excellent security through system keychains This approach allows users to maintain the same identity across different application types while each platform implements appropriate security measures for its environment.