LocalPass is a fully offline command-line password manager written in Rust. It stores credentials in a single encrypted vault file and never sends data over a network.
This project was built as a security-focused systems project for a resume portfolio. The main goal is to demonstrate practical cryptography usage, careful data handling, command-line application design, and test coverage around sensitive workflows.
- Offline encrypted vault stored as one local file
- Master password unlock without storing the master password
- Argon2id key derivation
- AES-256-GCM authenticated encryption
- Binary vault file header with magic bytes, version, salt, nonce, tag, and ciphertext
- Add, list, search, get, update, and delete credential entries
- Duplicate-site prevention so
get <site>stays unambiguous - Password generation with configurable length and symbols
- Generate-and-save workflow for new credentials
- Master password rotation with
rekey - Safe vault stats that do not expose usernames, passwords, or notes
- Unit and integration tests for crypto, vault format, CRUD, search, rekey, and CLI flows
- Rust 2024 edition
clapfor typed CLI parsingargon2for Argon2id key derivationaes-gcmfor AES-256-GCM encryptionserdeandserde_jsonfor encrypted vault payload serializationuuidandchronofor entry IDs and timestampsrandfor OS-backed randomnessrpasswordfor hidden password promptsarboardfor clipboard accessthiserrorfor typed errors
src/
main.rs interactive command handling and prompts
cli.rs typed CLI definitions
commands.rs storage-backed command helpers
crypto.rs Argon2id and AES-GCM
vault_file.rs binary vault file encoding
vault.rs in-memory vault operations
entry.rs credential entry model
generator.rs password generation
clipboard.rs clipboard copy and best-effort clearing
error.rs application error types
The app separates user interaction from testable command helpers. Integration tests call helper functions directly, which avoids brittle terminal automation while still testing encrypted vault behavior end to end.
The vault file is a flat binary file:
LPAS | version | salt | nonce | tag | ciphertext
The ciphertext is an AES-256-GCM encrypted JSON array of credential entries. Without the master password, vault contents are not readable through the LocalPass file format. If a wrong password is used, or if the vault is tampered with, AES-GCM authentication fails and LocalPass reports an unlock failure.
LocalPass is designed to protect a stolen vault file. An attacker who copies the vault should not be able to read or modify credentials without the master password.
Security properties:
- The master password is never stored.
- A 256-bit encryption key is derived at unlock time with Argon2id.
- Each save uses fresh encryption metadata.
- AES-GCM detects wrong passwords and file tampering.
get <site>copies to the clipboard by default instead of printing passwords.get <site> --showexists only for explicit demos and testing.list,search, andstatsnever print passwords.
Out of scope:
- Compromised operating systems
- Keyloggers
- Malware with access to the running process
- Physical access while the vault is unlocked
- Cloud sync and browser autofill
Default vault path:
~/.localpass/localpass.vault
Use --vault <path> for demos and tests:
cargo run -- --vault ./demo.vault <command>Command reference:
cargo run -- init
cargo run -- add github
cargo run -- list
cargo run -- search git
cargo run -- stats
cargo run -- get github
cargo run -- get github --show
cargo run -- update github
cargo run -- delete github
cargo run -- rekey
cargo run -- generate --length 24 --symbols
cargo run -- generate --length 24 --symbols --save gitlabadd and generate --save create new entries. If a site already exists, use update <site>.
cargo run -- --vault ./demo.vault init
cargo run -- --vault ./demo.vault add github
cargo run -- --vault ./demo.vault generate --length 24 --symbols --save gitlab
cargo run -- --vault ./demo.vault list
cargo run -- --vault ./demo.vault search git
cargo run -- --vault ./demo.vault stats
cargo run -- --vault ./demo.vault get gitlab --show
cargo run -- --vault ./demo.vault update github
cargo run -- --vault ./demo.vault rekeyAfter rekey, use the new master password. The old master password should no longer unlock the vault.
cargo build
cargo test
cargo clippy -- -D warningsThe integration tests use temporary vault files and cover encrypted end-to-end workflows.
Build an optimized binary:
cargo build --releaseRun it directly:
./target/release/localpass --help
./target/release/localpass initOptional: copy it into your local bin directory:
mkdir -p ~/.local/bin
cp target/release/localpass ~/.local/bin/localpass
localpass --helpOptimized release builds use link-time optimization, one codegen unit, and symbol stripping. Pushing a tag like v0.1.0 triggers the release workflow and uploads a Linux x86_64 binary archive.
git tag v0.1.0
git push origin v0.1.0- Built an offline password manager in Rust with a documented encrypted vault format.
- Used Argon2id and AES-256-GCM to protect vault contents.
- Designed clear module boundaries between CLI parsing, crypto, storage, and vault operations.
- Implemented master password rotation without changing the vault format.
- Added integration tests for encrypted workflows including add, update, delete, search, generate-save, and rekey.
- Documented the project threat model and avoided overclaiming security guarantees.
MIT
