vault: files sealed under a password that is never stored

Argon2id turns the vault password into a key that seals a random master
key; only the sealed copy is kept. Each file gets its own key, sealed
under the master key in its header with its media id, and its bytes are
AES-256-GCM STREAM records, so a swapped, cut or altered file refuses
to open. Uploads with ?encrypt=true are sealed as they stream in.

:vault, :unlock, :lock, :passwd, :encrypt, :decrypt and :upload! drive
it. The vault locks after WORKSPACE_VAULT_IDLE_MIN idle minutes, on
logout and on restart; while locked, sealed files answer 423, share
links never serve them, and :export! refuses rather than leave them out.

Sealing an existing file rewrites it under a new id and retires the old
one: the mirror deletes the plaintext from Proton Drive outright,
trash included, whatever WORKSPACE_BACKUP_PRUNE says, and drops it from
the readable files/ view. The mirror now compares on-disk sizes, so
sealed files are not re-hashed every run.
This commit is contained in:
nvrl committed 2026-10-19 16:03:59 +02:00
1 parent 364ba61963
commit a641d9b6ba
33 files changed
+1573 -54

No files matched your search

+6 -1
View File
@@ -2,13 +2,18 @@ use std::sync::Arc;
use sqlx::SqlitePool;
use crate::{backup::Backup, config::Config, notify::Notifier, throttle::LoginThrottle};
use crate::{backup::Backup, config::Config, notify::Notifier, throttle::LoginThrottle, vault::Vault};
#[derive(Clone)]
pub struct AppState {
pub db: SqlitePool,
pub config: Arc<Config>,
pub login_throttle: Arc<LoginThrottle>,
/// The vault password gets the same slowing-down as the login, kept apart
/// so guessing at one does not slow the other.
pub vault_throttle: Arc<LoginThrottle>,
/// Sealed files. Always present; holds no key until it is unlocked.
pub vault: Arc<Vault>,
/// The Proton Drive mirror. Always present; dormant until it has a session.
pub backup: Arc<Backup>,
/// Notification mail. Always present; dormant until WORKSPACE_SMTP_URL is set.