SHA256
1
0
Fork
You've already forked passwords
0
No description
  • Rust 71.1%
  • Slint 23%
  • Dockerfile 3.7%
  • Shell 2.2%
stewie 398cbc02ce Initial commit: minimal reproducible password manager
Slint dark-theme GUI with an anonymous anti-keylogger on-screen keyboard
(arrow-key navigation, selection re-randomised after every character).
Crypto:
- Argon2id (2 GiB) -> 1536-bit key split 1024+256+256
- per-subkey hash diversification: Whirlpool x2 / BLAKE3 / SHA3-256
- triple cascade: Serpent-256 -> Threefish-1024 -> AES-256-GCM (AEAD)
- single thread-safe Hash_DRBG CSPRNG (SHA-512), SHA3-512 seed
- X25519 sealed-box writes while locked, drained on unlock
- memory hardening: secrecy/zeroize, mlockall, no core dumps, no ptrace
Reproducible build: rust:1.92-alpine pinned by digest, Cargo.lock + cargo
vendor (--offline --locked), fixed clock/locale, scripts/build.sh --verify.
vendor/ is gitignored (~770 MB) and regenerated deterministically from
Cargo.lock.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026年06月02日 23:19:01 +02:00
.cargo Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
scripts Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
src Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
ui Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
.dockerignore Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
.gitignore Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
build.rs Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
Cargo.lock Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
Cargo.toml Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
Dockerfile Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
LICENSE Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
README.md Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
REQUIREMENTS.md Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00
rust-toolchain.toml Initial commit: minimal reproducible password manager 2026年06月02日 23:19:01 +02:00

passwords

License: AGPL-3.0-or-later Rust 1.92 UI: Slint Reproducible build Offline Vendored deps Crypto

A minimal, paranoid, fully reproducible password manager. Local only — no network, no telemetry, no plugins. A single encrypted SQLite database, a dark Slint GUI, and an optional anonymous on-screen keyboard that makes a keylogger useless even while you type the whole master password on the physical keyboard.

The authoritative specification is REQUIREMENTS.md; if the code and that document disagree, one of them is a bug. Reproducibility follows the org-wide standard in ../REPRODUCIBLE-BUILDS.md.

What makes it paranoid

  • One auditable source of randomness. A single, thread-safe Hash_DRBG-style CSPRNG over SHA-512 (seeded once from the OS, or from --seed <STRING>) produces every random byte: the KDF salt, all IVs/nonces, every ephemeral key, and the on-screen keyboard selection. Output is a one-way hash of the secret state, so observed output never reveals past or future values.
  • Anonymous on-screen keyboard (anti-keylogger). You navigate a grid with the arrow keys only and commit with Space — never typing the actual letters. The highlighted cell starts at a random position and jumps to a new random cell after every character, so the recorded arrow-key sequence has no fixed relation to your password. No mouse, no Enter, no F-keys on the grid.
  • Strong KDF. Master password → Argon2id with a 2 GiB memory cost → a 1536-bit key, split 1024 + 256 + 256.
  • Triple-layer cipher cascade. The payload is encrypted inner→outer with Serpent-256 (CBC) → Threefish-1024 (CBC) → AES-256-GCM (AEAD). The outer GCM authenticates everything (and the file header), and is the wrong-password / tamper detector.
  • Write-while-locked. Each database has an X25519 keypair. Locked, the master key and private key are wiped from RAM, existing entries are hidden, but you can still add entries — they are sealed to the public key and drained back in on unlock.
  • Memory hygiene. Secrets live in secrecy/zeroize types (auto-wiped, never logged). At startup the process does mlockall (no swap to SSD), RLIMIT_CORE = 0 and PR_SET_DUMPABLE = 0 (no core dumps, no ptrace).

The decrypted database lives only in RAM; the on-disk file is only the encrypted container — there is no plaintext SQLite header to fingerprint.

Using it

passwords [--db <PATH>] [--seed <STRING>]
  • Create a database: enter a path, leave Anonyme Bildschirmtastatur ticked (or not), click Erstellen, then enter the master password twice.
  • Open: same, click Öffnen, enter the master password once.
  • Anonymous keyboard: move with ↑ ↓ ← →, press Space to take the highlighted character, Backspace to delete. ⇧ = next char uppercase, ⇪ = caps lock. Click Öffnen/Erstellen when done.
  • In the list: User/Pass copy to the clipboard, deletes, Sperren 🔒 locks.

mlockall may need a higher limit for the full no-swap guarantee: run with ulimit -l unlimited (or grant CAP_IPC_LOCK). The app warns in the status line if it could not lock memory, and continues.

Reproducible build

Built only inside the pinned Docker image — Rust 1.92 on Alpine, pinned by content digest — strictly offline against the vendored sources in vendor/.

scripts/build.sh # build once -> ./out/{passwords,SHA256SUMS}
scripts/build.sh --verify # build twice and prove the hashes match

What pins the bytes: the base image digest, rust-toolchain.toml (1.92.0), Cargo.lock + vendor/ (--offline --locked), fixed SOURCE_DATE_EPOCH/ TZ/LC_ALL, --remap-path-prefix, and a fixed release profile (codegen-units=1, lto, strip, panic=abort). See the house standard.

Dependency version policy

We take the newest mutually-compatible version of every dependency, then freeze it via Cargo.lock + vendor/. One deliberate constraint: the cipher cascade (Serpent/Threefish/CBC) is held to the cipher 0.4 generation because the AES-256-GCM authenticator (aes-gcm) is published stable only on that generation; jumping the block ciphers to cipher 0.5 would mean dropping GCM authentication. Bumping is always a deliberate re-vendor commit, never silent. To re-vendor:

cargo update && cargo vendor # paste the printed [source.*] block into .cargo/config.toml

Threat model & honest limits

The anonymous keyboard defeats keyloggers, not screen recorders — a tool that captures the screen sees the highlighted cell. mlock/no-core-dump/no- ptrace raise the cost for spyware and crash forensics but do not stop an attacker who is already root. The triple cascade is defence-in-depth, not a proof; its security is at least that of AES-256-GCM. The custom CSPRNG follows a published construction (Hash_DRBG) and is kept small specifically so it can be audited (see src/csprng.rs and REQUIREMENTS.md §4).

Layout

Path What
REQUIREMENTS.md authoritative spec
src/csprng.rs central thread-safe Hash_DRBG CSPRNG (§4)
src/crypto.rs Argon2id KDF, triple cascade, sealed box (§6–8)
src/keyboard.rs anti-keylogger on-screen keyboard (§5)
src/db.rs in-RAM SQLite, encrypted container, lock/unlock (§7–9)
src/hardening.rs mlock / no-core-dump / no-ptrace (§8a)
src/ui.rs + ui/app.slint dark Slint GUI
Dockerfile, scripts/build.sh reproducible build

Licence

AGPL-3.0-or-later — see LICENSE.