Simple terminal-based password vault built with ncurses. It stores entries in a CSV-like file that is lightly obfuscated. Intended for learning and experimentation, not for protecting real secrets.
| login | help |
|---|---|
![]() |
![]() |
| show all | show id |
![]() |
![]() |
- Built and run on macOS (Darwin, ncurses).
- Expected to work on Linux and BSD variants with a C11 compiler and
ncursesinstalled. - Windows support is not verified; use WSL or a curses layer such as PDCurses/WinLibc if attempting a native build.
- Data is only XOR-obfuscated with the master password; this is not cryptographically secure.
- Use the program for testing and practice only; do not store sensitive credentials.
- The master password gates access but should be considered easily brute-forced if the DB is obtained.
How XOR obfuscation works (toy example):
Let P be a plaintext byte and K the matching byte of the key. The stored byte is C = P ⊕ K. To read, compute P = C ⊕ K. Example: P = 0x41 ('A'), K = 0x2B, then C = 0x41 ⊕ 0x2B = 0x6A; recovering: 0x6A ⊕ 0x2B = 0x41.
Prerequisites: C11-compatible compiler and ncurses development headers.
Clone from GitHub
# Prepare the dev directory, change it if it differs from yours ;-):
mkdir ~/dev/
cd ~/dev/
git clone https://github.com/rtulke/vaultdb.gitBuild locally:
makeInstall the binary (defaults to /usr/bin/vault, override with BINDIR=/custom/bin):
make installUninstall (prompts before deleting the database):
make uninstallPrerequisites: C11-compatible compiler and ncurses development headers and sudo.
Clone from GitHub
# Prepare the dev directory, change it if it differs from yours ;-):
mkdir ~/dev/
cd ~/dev/
git clone https://github.com/rtulke/vaultdb.gitBuild locally:
makeInstall the binary (defaults to /usr/bin/vault, override with BINDIR=/custom/bin):
sudo make installUninstall (prompts before deleting the database):
sudo make uninstall- Running as root stores the database at
/var/lib/vaultdb/vault.dband the log at/var/log/vault.log. - Running as a regular user stores the database at
~/.vault.dband the log at~/.vault.log.
Interactive vault for keeping test credentials: add, view, edit, delete entries with fields such as description, user, password, URL, tags, dates, and status. Provides a basic wizard, command logging, and tab completion in the TUI.
| Command | Description |
|---|---|
help |
Show available commands. |
show all |
List all entries in a table. |
show tag <t1> [t2...] |
List entries matching any of the given tags. |
show <id> |
Show details for entry by ID. |
show user <name> |
List entries for a user. |
show url <url> |
List entries whose URL contains the value. |
show date <dd.mm.yyyy> |
List entries created or updated on that date (prefix match). |
show status <value> |
List entries with a given status. |
show find <t1> [t2...] |
Search terms across description/user/url/tags/comment/status (all terms must match). |
add pw |
Add a new entry via wizard. |
change <id> |
Edit an entry via wizard. |
change pw <user> |
Replace all passwords for a user (optionally generate). |
change master-pw |
Set a new master password. |
rm pw <id1> [id2...] |
Delete entries by ID after confirmation. |
copy <id> |
Copy password to clipboard (auto-clears after 10s). |
lock |
Save, lock the vault, and require master password to unlock. |
history |
Show command history log. |
history clear |
Clear command history log. |
clear |
Clear the screen. |
version |
Show version/author info. |
shift+t <return> |
Toggle password visibility in the last shown detail view show <id>. |
quit / exit / q |
Save and exit. |
| Shortcut | Action |
|---|---|
Ctrl+T |
Toggle password visibility in the last shown detail view. |
Ctrl+C |
Cancel current input (does not exit the app). |
Ctrl+D |
End input (prompts return empty/exit current prompt). |
Ctrl+A |
Move cursor to start of line. |
Ctrl+E |
Move cursor to end of line. |
Ctrl+K |
Delete from cursor to end of line. |
Ctrl+U |
Delete from start of line to cursor. |
Ctrl+W |
Delete previous word. |
Ctrl+L |
Clear screen and redraw prompt. |
Arrow Up/Down |
Browse session command history and recall previous inputs. |
Tab / double Tab |
Trigger command completion and show suggestions. |
- ncurses TUI with colorized header/body and centered dialogs.
- Auto-lock after 5 minutes of inactivity.
- Tab completion for commands, IDs, users, tags, and statuses.
- Cross-field search via
show find(description/user/url/tags/comment/status). - Copy password to clipboard for 10s via
copy <id>(pbcopy/xclip/xsel/wl-copy/clip). - Passwords are masked in table views; view details or copy to clipboard to reveal.
- Toggle password visibility in detail view via
Ctrl+T/toggleafter ashow <id>. - Extra fields: OTP/TOTP secret, security question, favorite flag; table shows a Fav column (
*). - Obfuscated CSV database persisted to
~/.vault.db(or system locations when root) with fieldsid,description,user,password,url,comment,tags,createdate,updatedate,status,otp,security_question,favorite. - Command history logging to
~/.vault.log. - Action logging with timestamps for add/change/delete/password ops and lock/unlock events.
- Wizard-driven entry creation and edits, including optional password generation.
1digits,2letters,3alnum,4digits+specials,5letters+specials,6alnum+specials,7alnum+common-special.- Special set defaults to
!@#$%^&*()-_=+[]{};:'",.<>/?\~`; can be overridden when choosing a special mode.
- Strong encryption & KDF: AES-GCM + Argon2id (configurable memory/iterations) with auth-tag check.
- Master password policies: length/complexity checks and weak-password warnings.
- Field-level extras: OTP/TOTP fields, security questions, favorite/starred flag.
- Password reveal toggle in detail view (not only table masking).
- Entry expiry/reminders: expiry date with warning for expired entries.
- Backup/Import/Export: encrypted export/import (age/openssl), warn on plaintext; auto encrypted backup on save.
- Search/Filter: fuzzy search, combined filters (tag+user+status), sorting (updated desc/status), quick search alias, optional
--jsonoutput. - Clipboard enhancements: configurable timeout; copy user/URL/OTP.
- Audit/log options: toggle logging or reduce to errors/events without command text.
- Config file:
~/.vaultdbrcfor defaults (DB path, auto-lock, clipboard timeout, colors, readonly). - Multimaster/Key rotation: rotate master password with re-encrypt in one step.
- Entry templates: predefined templates (Web, SSH, API token) with suitable fields/status.
- TOTP: store secret and generate codes (if dependencies acceptable).
- Quick search: global
findalias and optional--jsonoutput for scripting. - Tests: unit tests for parser/save/load/encrypt; integration test (temp DB add/show/rm); fuzz CSV parser.
Purpose-built for demonstrations to highlight the weak XOR obfuscation. Do not use for unauthorized access.
Reads candidates from the wordlist until the CSV header decrypts.
python3 scripts/bruteforce.py wordlist --db ~/.vault.db --wordlist /path/to/wordlist.txtpython3 scripts/bruteforce.py exhaustive --db ~/.vault.db --min-len 4 --max-len 6 --charset alnum-special --special "%$#-+." --workers 4Enumerates every combination in the length range using charset presets:
digits,letters,alnum,special,digits-special,letters-special,alnum-special--specialoverrides the special-character set for presets that include specials.--workerssets parallel processes (default: detected CPU cores). Note that search space grows exponentially with length; keep ranges small for tests.- Common special-character sets in real-world passwords often include symbols like
!@#$%^&*()-_=+[]{};:'",.<>/?\~. Use--special` to reflect the set you want to test.
| Parameter | Subcommand | Description |
|---|---|---|
--db PATH |
both | Path to database (default: ~/.vault.db). |
--wordlist PATH |
wordlist | Wordlist file, one candidate per line (required). |
--min-len N / --max-len N |
exhaustive | Minimum / maximum key length (required). |
--charset {digits,letters,alnum,special,digits-special,letters-special,alnum-special,common-special,custom} |
exhaustive | Charset preset for generator. |
--special CHARS |
exhaustive | Override special characters for presets that include specials (special, digits-special, letters-special, alnum-special, common-special); default specials: !@#$%^&*()-_=+[]{};:'",.<>/?\~`. |
--chars CHARS |
exhaustive | Custom charset when using --charset custom. |
--workers N |
exhaustive | Parallel processes (default: detected CPU cores if omitted; e.g., --workers 4 forces 4 workers even if more cores are available). |
--max-tries N |
both | Abort after N candidates. |
--time-limit SECONDS |
both | Abort after N seconds. |
--progress-every N |
both | Print progress every N attempts (defaults: 100000 wordlist, 50000 exhaustive). |
--max-matches N |
both | Stop after N matches (default: 1). |
--quiet |
both | Suppress progress output. |
| Charset presets | Description |
|---|---|
digits |
0-9 |
letters |
a-zA-Z |
alnum |
a-zA-Z0-9 |
special |
default !@#$%^&*()-_=+[]{};:'",.<>/?\~, override via --special`) |
digits-special |
0-9 + special set |
letters-special |
a-zA-Z + special |
alnum-special |
a-zA-Z0-9 + special |
common-special |
letters+digits+default specials |
custom |
use --chars "..." |
Example runs:
On an Apple M4 MacBook Pro (10 performance/efficiency cores visible), omitting --workers uses all detected cores. Specifying --workers N caps parallelism (e.g., --workers 4 uses 4 workers even if 10 are available).
# Minimal wordlist run with default DB — runtime depends on list size; a few million entries finish in seconds.
python3 scripts/bruteforce.py wordlist --wordlist /tmp/rockyou.txt# Wordlist run with caps and quieter progress — 500k tries cap stays well under 10s at tens of millions checks/sec.
python3 scripts/bruteforce.py wordlist --db ~/.vault.db --wordlist ./small.txt --max-tries 500000 --time-limit 10 --progress-every 20000# Stop after first two matches from wordlist — duration depends on where matches appear.
python3 scripts/bruteforce.py wordlist --wordlist ./candidates.txt --max-matches 2# Exhaustive: digits only, 4–6 chars, 4 workers — ~1.1 million combos; sub-second at ~50M+ checks/sec.
python3 scripts/bruteforce.py exhaustive --min-len 4 --max-len 6 --charset digits --workers 4# Exhaustive: alnum+special with custom specials, 4–5 chars, 6 workers — ~85 billion combos; hours to a day+ if fully searched (use limits).
python3 scripts/bruteforce.py exhaustive --min-len 4 --max-len 5 --charset alnum-special --special "%$#-+." --time-limit 15 --workers 6# Exhaustive: common-special preset, length 4, stop after 100k — full space ~14 billion combos; capped run completes quickly, full run would take minutes to hours.
python3 scripts/bruteforce.py exhaustive --min-len 4 --max-len 4 --charset common-special --max-tries 100000# Exhaustive: custom charset, very small space — 7^3=343 combos; instant.
python3 scripts/bruteforce.py exhaustive --min-len 3 --max-len 3 --charset custom --chars "abc123!" --progress-every 5000# Exhaustive: run quietly (no progress logs) — letters len 4 => 26^4≈456k combos; sub-second to a couple seconds.
python3 scripts/bruteforce.py exhaustive --min-len 4 --max-len 4 --charset letters --quiet# Exhaustive: common-special, len 4–8, auto-workers (~10 on an M4) — search space ~5×10^15 combos; even at ~100M/s aggregate this would take ~1.6 years, so use smaller ranges or wordlists instead.
python3 scripts/bruteforce.py exhaustive --min-len 4 --max-len 8 --charset common-specialUse only for legal testing/education; these lists can be very large.
- https://github.com/danielmiessler/SecLists (Passwords/Leaked-Databases, Passwords/Common-Credentials)
- https://github.com/berzerk0/Probable-Wordlists
- https://github.com/jeanphorn/wordlist
- https://github.com/kkrypt0nn/Wordlists
- https://github.com/kaonashi-passwords/Kaonashi
- https://crackstation.net/crackstation-human-only.txt.gz
- https://download.weakpass.com/wordlists/ (multiple mega/gigabyte dumps)
- https://haveibeenpwned.com/Passwords (Pwned Passwords download/API; SHA-1 hashes)
- https://github.com/PrinceDhaliwal/WordList-Collection
- https://https://github.com/topics/wordlist (GitHub Collection with Tags "wordlist")
- https://github.com/insidetrust/statistically-likely-usernames (usernames, sometimes paired with small password sets)



