Skip to content

Latest commit

ย 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

README.md

โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—    โ–ˆโ–ˆโ•—   โ–ˆโ–ˆโ•— โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•—   โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•—     โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—
โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•โ•โ•    โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘     โ•šโ•โ•โ–ˆโ–ˆโ•”โ•โ•โ•
โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—    โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘        โ–ˆโ–ˆโ•‘
โ–ˆโ–ˆโ•”โ•โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘    โ•šโ–ˆโ–ˆโ•— โ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘   โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘        โ–ˆโ–ˆโ•‘
โ–ˆโ–ˆโ•‘     โ–ˆโ–ˆโ•‘  โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘     โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ• โ–ˆโ–ˆโ•‘  โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•”โ•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—   โ–ˆโ–ˆโ•‘
โ•šโ•โ•     โ•šโ•โ•  โ•šโ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•      โ•šโ•โ•โ•โ•  โ•šโ•โ•  โ•šโ•โ• โ•šโ•โ•โ•โ•โ•โ• โ•šโ•โ•โ•โ•โ•โ•โ•   โ•šโ•โ•

Cybersecurity Projects Tier: Foundations Difficulty: Hardest Foundation Python 3.13 Argon2id AES-256-GCM License: AGPLv3 Tests Lint

Encrypted command-line password manager โ€” Argon2id key derivation, AES-256-GCM authenticated encryption, atomic durable writes, advisory file locking. One master password protects every credential you trust to it.

This is a quick overview โ€” security theory, architecture, and full walkthroughs are in the learn modules.

Note

Foundations tier โ€” the hardest of the three. This is a stepping stone into the beginner tier. It assumes no prior Python experience but ramps faster than hash-identifier and http-headers-scanner. The source is heavily commented as a teaching aid, the learn/ folder explains every cryptographic idea from zero, and every Python feature is introduced when it first appears. If "what's a @dataclass" feels like the wrong question, start with hash-identifier first.

What It Does

  • Stores credentials in a single encrypted JSON file at ~/.password-vault/vault.json (mode 0600)
  • Derives a 32-byte AES key from your master password via Argon2id (OWASP-recommended parameters, ~0.5s per derivation)
  • Encrypts vault contents with AES-256-GCM โ€” confidentiality + tamper detection in one primitive
  • Atomic, durable, concurrent-safe writes: tmp file โ†’ fsync โ†’ atomic rename โ†’ directory fsync, with advisory fcntl lock to serialize concurrent pv invocations
  • Master password rotation that re-encrypts the entire vault under a fresh salt and key
  • Cryptographically secure password generator using secrets (never random) with a Fisher-Yates shuffle on top of secrets.randbelow
  • Stores KDF parameters in the file โ€” old vaults remain readable when defaults change, and rotation can upgrade them transparently
  • Typed exception hierarchy (WrongPasswordError, VaultFormatError, EntryNotFoundError, โ€ฆ) for precise error handling
  • Rich-rendered colored panels and tables; pipe-friendly stdout/stderr separation
  • Refuses to distinguish "wrong password" from "tampered file" โ€” both look the same cryptographically, exposing the difference helps attackers

Quick Start

./install.sh
just run -- init
just run -- add github
just run -- get github
$ pv init
New master password: ************
Confirm master password: ************
Vault created at /home/you/.password-vault/vault.json

$ pv add github
Username for github: alice
Password for github (hidden): ************
URL (optional, press Enter to skip): https://github.com
Notes (optional, press Enter to skip):
Added entry: github

$ pv get github
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ github โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ username   alice                           โ”‚
โ”‚ password   hunter2-but-better              โ”‚
โ”‚ url        https://github.com              โ”‚
โ”‚ created    2026-05-13T14:22:10+00:00       โ”‚
โ”‚ updated    2026-05-13T14:22:10+00:00       โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Tip

This project uses just as a command runner. Type just to see all available recipes.

Install: curl -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin

Commands

Command What it does
pv init Create a new empty vault. Prompts for the master password twice.
pv add <name> Add an entry. Prompts for username, password, optional URL and notes. --generate / -g to use a random password.
pv get <name> Show every field of one entry in a colored panel.
pv list Print every entry name as a table (no passwords shown).
pv delete <name> Remove an entry by name.
pv gen [length] Generate a strong random password and print it to stdout. No vault required.
pv change-password Rotate the master password โ€” re-encrypts the entire vault under a fresh salt and key.

Every command takes --vault PATH (or $PV_VAULT) to point at an alternate vault file.

Demo: pipe-friendly generation

# Generate and copy to clipboard (macOS)
just run -- gen 32 | pbcopy

# Generate and copy to clipboard (Linux)
just run -- gen 32 | xclip -selection clipboard

# Generate into a shell variable
PASSWORD=$(just run -- gen 32)

# Letters + digits only, no symbols
just run -- gen 24 --no-symbols

Important

pv never accepts the master password as a CLI flag. Passwords passed as flags leak into shell history (history command) and process listings (ps aux). Every prompt uses getpass.getpass() โ€” same primitive sudo uses โ€” so the password is never echoed and never logged.

Cryptographic guarantees

Concern Mitigation
Vault file stolen Argon2id with 64 MiB / 3 passes / 4 lanes makes each guess ~0.5s; a billion guesses โ‰ˆ 15 years
Vault file tampered AES-GCM authentication tag refuses to decrypt; same error as "wrong password" by design
Power loss mid-save Atomic write: tmp โ†’ fsync โ†’ os.replace โ†’ parent-dir fsync. Always old-or-new, never half
Two pv processes racing Advisory fcntl.LOCK_EX on sidecar .lock file (POSIX; NTFS atomic-rename on Windows)
Vault tmp world-readable os.open with mode 0o600 at the very first syscall โ€” no chmod race window
Predictable random output secrets module everywhere โ€” for salts, nonces, passwords, and the Fisher-Yates shuffle
Aging KDF parameters Parameters stored in the vault file; change-password can upgrade them transparently
KDF parameter corruption Validated against Argon2's algorithmic floors on load; clean VaultFormatError instead of library crash
Forward-incompatible format Top-level version field; future versions can refuse or migrate

What this project does not defend against โ€” and why โ€” is documented honestly in learn/01-CONCEPTS.md ยง12.

Tooling

just            # list available recipes
just test       # run pytest (60+ tests across crypto, vault, generator)
just test-cov   # tests + coverage report
just lint       # ruff + mypy + pylint
just format     # yapf
just run -- <cmd> [args]

Requirements

  • Python 3.13+ โ€” the install script will check.
  • uv โ€” modern Python package manager (auto-installed by ./install.sh).
  • just โ€” command runner (auto-installed by ./install.sh).
  • Linux, macOS, or WSL2 strongly recommended over native Windows โ€” file locking and directory fsync paths are POSIX-flavored. NTFS gives atomic os.replace regardless, so native Windows works with reduced concurrency guarantees.

No compilers or system libraries beyond what argon2-cffi and cryptography install through uv. No network access required at runtime.

Learn

This project includes step-by-step learning materials covering the security theory, architecture, and implementation โ€” written for someone who has never touched Python or cryptography before. Read them in order.

Module Topic
00 - Overview Quick start, prerequisites, project layout, common problems
01 - Concepts What encryption is, KDFs, Argon2id, salts, AES-GCM, nonces, the threat model, real breaches
02 - Architecture Five-file layout, on-disk format, per-command flow diagrams, the atomic-write pipeline
03 - Implementation Line-by-line walkthrough of every source file โ€” every Python feature explained when first encountered
04 - Challenges Fifteen extension ideas across four tiers, from a search command to porting the vault format to another language

See Also

License

AGPL 3.0