Files
narl-workspace/Cargo.toml
T
nvrl cd18f80c04 backup: keep Proton key passphrases, never the password
The stored session used to hold the mailbox password, which on a
single-password account is the login password. It now holds the per-key
passphrases derived from it at login, which unlock the keys but cannot
log in, change the password or turn 2FA off. Login also checks them
against the account's keys, so a wrong mailbox password fails there
rather than at the first backup.

A session stored by an older build is upgraded on the next start: its
key salts are already known, so the passphrases derive locally and the
file is rewritten without the password.
2026-10-19 16:48:43 +02:00

76 lines
3.0 KiB
TOML

[package]
name = "narl-workspace"
version = "0.1.0"
edition = "2021"
description = "A terminal-themed personal diary for the browser"
[dependencies]
axum = { version = "0.8", features = ["multipart", "macros"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal", "fs", "io-util"] }
tower = "0.5"
tokio-util = { version = "0.7", features = ["io"] }
tower-http = { version = "0.6", features = ["trace", "compression-gzip", "limit", "set-header"] }
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio", "sqlite", "migrate", "macros"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
dotenvy = "0.15"
uuid = { version = "1", features = ["v4"] }
rand = "0.8"
hmac = "0.12"
sha2 = "0.10"
base64 = "0.22"
subtle = "2"
mime_guess = "2"
rust-embed = { version = "8", features = ["interpolate-folder-path"] }
regex = "1"
anyhow = "1"
zip = { version = "2", default-features = false, features = ["deflate"] }
tempfile = "3.27.0"
# Only for `--features keyring`, on a host that has a Secret Service; the
# container deployment has no session bus and falls back to the session file.
keyring = { version = "3", features = ["sync-secret-service", "crypto-rust"], optional = true }
# Mail. rustls rather than native-tls: the container has no OpenSSL, and the
# Proton client already pulls rustls in.
lettre = { version = "0.11", default-features = false, features = ["smtp-transport", "pool", "builder", "hostname", "tokio1-rustls-tls"] }
# "did I write today?" and "is this due today?" are local-day questions, and DST
# rules out doing them with a fixed offset.
chrono = { version = "0.4", default-features = false, features = ["clock", "std"] }
chrono-tz = "0.10"
# The vault: files encrypted at rest under a key only a password unlocks.
# AES-256-GCM in the STREAM construction, so a file of any size is sealed and
# opened a chunk at a time; Argon2id between the password and the key.
aes-gcm = { version = "0.10", features = ["stream"] }
argon2 = "0.5"
zeroize = { version = "1", features = ["serde"] }
futures-util = { version = "0.3", default-features = false, features = ["std"] }
proton-drive-rs = "0.9.2"
proton-sdk = "0.9.2"
rpassword = "7"
hex = "0.4"
# SFTP mount: spaces and folders as a filesystem, authenticated by pubkey
# instead of the cookie session. `ring` rather than the default `aws-lc-rs`
# backend, because rustls (via lettre) already pulls `ring` in.
russh = { version = "0.63", default-features = false, features = ["ring", "rsa"] }
russh-sftp = "3"
# Only for generating the host key at first boot — ssh-key needs an rng that
# speaks rand_core 0.10, one major version past the `rand` used everywhere else.
rand10 = { package = "rand", version = "0.10" }
[features]
default = []
# Keep the Proton session in the OS keyring instead of a 0600 file. Needs a
# Secret Service on D-Bus, so it is off for the container deployment.
keyring = ["dep:keyring"]
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true