Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

secure-password-manager-cpp

A command-line password manager written in modern C++ (C++17), using real, audited cryptography from OpenSSL — not a hand-rolled cipher. It stores credentials in a single vault file that is encrypted and authenticated with AES-256-GCM, unlocked by a master password that is never written to disk.

Author: Syed Muhammad Waleed Bukhari (@WalBuk28) · Cybersecurity Engineer

Cryptographic design

Concern Choice Why
Confidentiality + integrity AES-256-GCM Authenticated encryption — a modified vault is detected, not silently mis-decrypted.
Master-password → key PBKDF2-HMAC-SHA256, 200 000 iterations, 16-byte random salt Slows brute-force; a per-vault salt defeats rainbow tables.
Nonce Fresh 96-bit random IV every save GCM nonces must never repeat under one key.
Master password Derived to a key, never stored Only the salt + iteration count live in the file.
Secret entry Terminal echo disabled (termios) Secrets don't hit the screen or scrollback.
Key material in RAM OPENSSL_cleanse on buffers Best-effort wipe; not optimised away by the compiler.

Vault file format

magic "SPM1" | salt(16) | iterations(4, big-endian) | iv(12) | tag(16) | AES-256-GCM ciphertext

The ciphertext is a length-prefixed serialisation of the credential entries, so there is no plaintext structure to leak on disk.

Project layout

include/spm/   crypto.hpp · vault.hpp · entry.hpp     (public API)
src/           crypto.cpp   OpenSSL EVP wrappers (PBKDF2, AES-256-GCM)
               vault.cpp    load/save, (de)serialisation, entry management
               main.cpp     CLI (init/add/get/list/remove, hidden input)
tests/         test_spm.cpp unit tests (CTest)
CMakeLists.txt OpenSSL discovery, warnings-as-signal, test registration

crypto knows nothing about vaults; vault composes it; main is a thin CLI.

Build

Requires CMake ≥ 3.16, a C++17 compiler and OpenSSL (libcrypto) dev headers.

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
ctest --test-dir build --output-on-failure

Usage

export SPM_VAULT=~/.spm/vault.spm      # optional; defaults to ./vault.spm

./build/spm init                       # create a vault (prompts master password twice)
./build/spm add github walbuk28        # prompts for the secret, stores it
./build/spm get github                 # prints username + password
./build/spm list                       # lists services
./build/spm remove github

Security properties, demonstrated

# wrong master password
$ spm get github
error: authentication failed — wrong password or tampered vault      (exit 1)

# flip a single byte of vault.spm, then open it
$ spm list
error: authentication failed — wrong password or tampered vault      (exit 1)

# the stored secret never appears in the file in plaintext
$ grep -c "super-secret-value" vault.spm
0

Tests

ctest runs a suite covering key derivation (deterministic per salt, unique across salts/passwords), the AES-256-GCM encrypt/decrypt round-trip, wrong-key rejection, single-bit tamper detection, and a full vault save/load round-trip including entry replacement and wrong-password failure.

Threat model & limitations

Designed to protect credentials at rest — against theft or modification of the vault file. It does not defend against a compromised host that can read process memory or keystrokes while the vault is unlocked. A production successor would add: a memory-locked (mlock) secret buffer, clipboard-free retrieval, and Argon2id in place of PBKDF2.

License

MIT © Syed Muhammad Waleed Bukhari

About

A CLI password manager in modern C++ using AES-256-GCM and PBKDF2 (OpenSSL), with CMake and CTest.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages