Skip to content

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.