390 lines
No EOL
12 KiB
Markdown
390 lines
No EOL
12 KiB
Markdown
# 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<u8>, // seed encrypted under KEK
|
|
kdf: String, // "HKDF-SHA256"
|
|
cipher: String, // "XChaCha20-Poly1305"
|
|
salt: Vec<u8>, // 32-byte salt for KEK derivation
|
|
nonce: Vec<u8>, // 24-byte nonce for encryption
|
|
public_key: Vec<u8>, // 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 <FILE> [--security-level LEVEL]
|
|
```
|
|
|
|
4. **`export`** - Export Passport to .spf file
|
|
```bash
|
|
sharenet-passport export <FILE> [--output FILE]
|
|
```
|
|
|
|
5. **`info`** - Display Passport details
|
|
```bash
|
|
sharenet-passport info [FILE]
|
|
```
|
|
|
|
6. **`sign`** - Sign a message (testing)
|
|
```bash
|
|
sharenet-passport sign <FILE> <MESSAGE>
|
|
```
|
|
|
|
### 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. |