Encrypted at rest
AES-256-GCM, fresh 96-bit nonce per entry.
A password-secured local vault · scrypt → AES-256-GCM · QR air-gap transport
# the only hard dependency pip install cryptography # optional — QR transport only pip install qrcode pillow pyzbar # fetch the vault (single file) curl -O https://myaelmendez.github.io/vaeult/vaeult.py
python væult.py init # passphrase ×2, min 8 chars python væult.py set STRIPE_KEY # value read hidden python væult.py get STRIPE_KEY # print to stdout python væult.py list # names only — never values python væult.py verify # round-trip · tamper · name-binding # QR air-gap — carries the SEALED blob, never plaintext python væult.py qr STRIPE_KEY # → QR PNG python væult.py qr-open qr.png # decode + import
AES-256-GCM, fresh 96-bit nonce per entry.
GCM auth tag — a flipped byte fails closed.
Entry name is AEAD associated data — a renamed entry won't open.
Sealed sentinel → clear refusal, not a crypto error.
Write .tmp then os.replace.
Never makes a request. Cannot exfiltrate by design.
| Element | Ships? |
|---|---|
| væult.py (the tool) | ✓ open, MIT |
| *.væult (your encrypted secrets) | ✗ never |
| passphrase | ✗ never stored, logged, or sent |
| QR payload | sealed envelope — inert without the passphrase |
The tool is open. The secrets are not.