Encryption¶
Primitives¶
| Use | Algorithm | Parameters |
|---|---|---|
| Key derivation | Argon2id | 128 MB memory, 3 iterations, 4 parallelism |
| Subkey separation | HKDF-SHA256 | Distinct info strings per derived key |
| Vault encryption | XChaCha20-Poly1305 | 192-bit random nonce per record |
| Public-key wrap (team vaults) | X25519 + XChaCha20-Poly1305 | Vault key wrapped per member |
| Sync payload | XChaCha20-Poly1305 | Same key, distinct nonce per payload |
All implementations are pure-Rust crates: argon2, hkdf, chacha20poly1305, x25519-dalek. No platform-specific crypto.
Key tree¶
password + account_id
│
├── Argon2id(salt = account_id) ──► master
│ │
│ ├── HKDF("auth") ──► auth_key → server login
│ └── HKDF("enc") ──► enc_key → XChaCha20-Poly1305, local vault + SSE payloads
│
└── (Gist sync)
passphrase + manifest_salt
└── Argon2id → HKDF("gist") ──► gist_enc_key
What's encrypted vs. metadata¶
| Field | Encrypted? |
|---|---|
| Passwords | ✓ |
| Private keys | ✓ |
| Snippet contents | ✓ |
| Hostnames, ports, usernames | metadata (not encrypted in the local file) |
| Tags, folders | metadata |
| Notes | ✓ |
For sync, everything in the payload is encrypted — including metadata. The split above is only on the local vault file, optimized for fast list rendering.
Vault file format¶
voltius.vault.v1
├── header (cleartext)
│ ├── version
│ ├── kdf params (Argon2id memory / iters / salt)
│ ├── HKDF info strings
│ └── metadata index
└── records
└── per-record { nonce (24B), ciphertext, tag (16B) }
Each record encrypts independently. Corruption of one record doesn't take down the file.
Crate¶
The implementation is open and shared between Tauri (native) and web portal (WASM) via voltius-crypto. The core logic lives in crates/voltius-crypto/src/lib.rs.