# black-bag
`black-bag` is a zero-trace, no-compromise command-line vault for high-risk operators. It ships as a single Rust binary with the strongest defaults we can provide: Argon2id hardening, ML-KEM-1024 cascaded wrapping (Kyber), XChaCha20-Poly1305 payload encryption, zeroization of every secret buffer, and page-locked memory on Unix. There is no optional telemetry, no cloud, no GUI—just a laser-focused CLI that keeps secrets safe even under hostile conditions.
## Highlights
- **Zero-trace posture** – secrets never touch stdout, logs, temp files, or the clipboard. All input happens via hidden TTY prompts and is stored only after AEAD encryption.
- **Modern crypto pipeline** – Argon2id → ML-KEM-1024 (Kyber) → random 32-byte DEKs sealed with XChaCha20-Poly1305. Writes are atomic/fdatasync’d with strict permissions and zeroized in memory on drop.
- **Rich record catalogue** – logins, contacts, identity docs, secure notes, payment cards, SSH keys, PGP keys, TOTP seeds, recovery kits, bank accounts, Wi-Fi profiles, API credentials, and crypto wallets. Every record supports tagging and full-text queries.
- **Cross-platform parity** – builds cleanly on macOS, Linux, and Windows. `mlock` is enabled automatically on supported Unix platforms and degrades gracefully elsewhere.
- **Security by default** – all protective features are enabled in every binary; there are no configuration flags that weaken the threat posture.
## Quick start
```bash
# prerequisites: Rust toolchain 1.81+ (via rustup) and a standard build environment
cargo build --release
install -m 0755 target/release/black-bag ~/.local/bin/black-bag
black-bag --help
```
Recommended hygiene:
- Run from an encrypted disk.
- Disable shell history or use `HISTCONTROL=ignorespace` with leading spaces.
- Set `RUST_BACKTRACE=0` in operational shells.
## Creating your vault
```bash
black-bag init --mem-kib 262144
```
You’ll be prompted for the master passphrase twice. The vault stores under the platform data directory (e.g., `~/.config/black_bag/vault.cbor`).
## Adding records
```bash
# login
black-bag add login --title "Ops Portal" --username phoenix --url https://ops.example --tags mission
# contact
black-bag add contact --full-name "Analyst Zero" --emails a0@example --phones "mobile:+1-555-0101,desk:+1-555-0110" --tags handler
# identity document
black-bag add id --id-type passport --name-on-doc "Alex Smith" --number X1234567 --issuing-country US --expiry 2032-08-01
# secure note
black-bag add note --title "Fallback Protocol" --tags red-team
# bank account
black-bag add bank --institution "First Federal" --account-name "Ops budget" --routing-number 021000021 --tags finance
# Wi-Fi profile
black-bag add wifi --ssid "safehouse-net" --security WPA2 --location Berlin --tags infrastructure
# API credential
black-bag add api --service intel-api --environment production --access-key AKIA-123 --scopes read,write --tags automation
# crypto wallet
black-bag add wallet --label btc-cold --asset BTC --address bc1q... --network mainnet --tags treasury
# totp secret
black-bag add totp --title "GitHub MFA" --issuer GitHub --account you@example --secret JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP
# totp codes
black-bag totp code <UUID> --time 59
```
Sensitive fields (passwords, passphrases, API secrets, private keys) are collected via hidden prompts after the command issues—nothing sensitive ever appears in argv or shell history.
## Listing, filtering, and querying
```bash
black-bag list # masked summaries
black-bag list --kind bank_account # filter by record family
black-bag list --tag mission # filter by tag
black-bag list --query opsnet # full-text search across metadata
```
Inspect a specific record:
```bash
black-bag get <UUID>
black-bag get <UUID> --reveal # requires an interactive TTY
```
## Rotation, health, and recovery
- `black-bag rotate` – rewraps the master DEK with fresh randomness.
- `black-bag doctor` – prints health info (Argon2 params, feature flags, item counts).
- `black-bag recovery split` / `combine` – manage Shamir shares for catastrophic recovery.
- `black-bag version` – display binary version, target, and compiled features (mlock, pq, fuzzing, etc.).
- `black-bag backup keygen/sign/verify` – manage ML-DSA-87 (or legacy Ed25519) authenticity for offline backups.
## CLI Command Reference
| `black-bag init [--mem-kib <KiB>]` | Create a new vault with Argon2id + ML-KEM-1024 wrapping | Default memory cost: 262 144 KiB (256 MiB) |
| `black-bag add <record-type> [...]` | Add login/contact/id/note/bank/wifi/api/wallet/totp/ssh/pgp/recovery records | Sensitive fields captured via hidden prompts |
| `black-bag list [--kind KIND] [--tag TAG] [--query Q]` | Show masked summaries | Combine filters for scoped audits |
| `black-bag get <UUID> [--reveal]` | Inspect records; optionally reveal secrets on a TTY | `--reveal` denied on non-interactive stdout |
| `black-bag totp code <UUID> [--time <UNIX>]` | Generate TOTP codes | Supports historic/time-skew analysis |
| `black-bag rotate [--mem-kib <KiB>]` | Rewrap master DEK with fresh randomness | Optional Argon2 memory override |
| `black-bag doctor [--json]` | Print health diagnostics | JSON output ready for monitoring pipelines |
| `black-bag recovery split/combine` | Manage Shamir shares for disaster recovery | Configurable thresholds and share counts |
| `black-bag backup keygen/sign/verify` | Manage ML-DSA-87 (or Ed25519) backup signatures | Produces `.int` + `.int.sig` companions |
| `black-bag selftest` | Run embedded round-trip checks | Useful after upgrades or migrations |
| `black-bag version` | Display build version, target, and enabled features (`mlock`, `pq`, `fuzzing`) | Validate release binaries |
### Backup workflow (PQ-safe)
```bash
# one-time: generate ML-DSA-87 keys for signing sidecars
black-bag backup keygen --pub-out backup.mldsa87.pub --sk-out backup.mldsa87.sk
# copy the ciphertext and immediately mint/update integrity + signature sidecars
cp ~/.config/black_bag/vault.cbor /offline/vault-$(date +%Y%m%d).cbor
black-bag backup sign \
--path /offline/vault-$(date +%Y%m%d).cbor \
--key backup.mldsa87.sk \
--pub-out /offline/backup.mldsa87.pub
# later, verify both bit-rot and authenticity before restore
black-bag backup verify \
--path /offline/vault-$(date +%Y%m%d).cbor \
--pub-key /offline/backup.mldsa87.pub
```
The signing command produces two companions next to the ciphertext: `vault-*.cbor.int` (BLAKE3 tag keyed with the ML-KEM public key) and `vault-*.cbor.int.sig` (ML-DSA-87 or Ed25519 signature). Ship all three files together and treat any verification failure as tampering until proven otherwise.
### Rotation, health, and recovery
- `black-bag rotate` – rewraps the master DEK with fresh randomness.
- `black-bag doctor` – prints health info (Argon2 params, feature flags, item counts).
- `black-bag recovery split` / `combine` – manage Shamir shares for catastrophic recovery.
- `black-bag selftest` – quick sanity check of encryption/decryption paths.
- `black-bag version` – confirm binary target/profile and compiled features (`mlock`, `pq`, etc.).
## Threat model (summary)
See [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md) for assumptions, adversary capabilities, and residual risks. Treat the vault ciphertext as sensitive and keep backups offline.
## Building and testing
```bash
cargo fmt
cargo clippy --all-targets --all-features
cargo test
```
CI should run the same three commands on every commit. Tests cover cryptographic round-trips, helper utilities, and zero-trace guarantees.
## Memory Locking (mlock)
On Unix platforms, when built with the default `mlock` feature, black-bag locks sensitive memory (passphrases, DEKs, and secret buffers) using `mlock(2)` for the lifetime of those values and unlocks it on drop. This reduces the risk of secrets being paged to disk.
- Status check: `black-bag doctor` reports whether `mlock` is enabled and functional on the host.
- macOS: `mlock` generally works for unprivileged processes within system limits. If you run into failures, check per-process limits with `ulimit -l` and consider adjusting them in your launch environment.
- Linux: `mlock` requires sufficient `RLIMIT_MEMLOCK` or `CAP_IPC_LOCK`.
- Temporary session limit (KB): `ulimit -l 65536` (example: 64 MiB)
- Or grant the binary capability (use with care): `sudo setcap cap_ipc_lock=+ep $(command -v black-bag)`
Notes:
- Locking is best‑effort; when the OS refuses the lock, black-bag continues to function but warns in `doctor` output. You should raise limits until `doctor` reports `mlock: enabled and working`.
- On non‑Unix targets, the `mlock` feature is ignored and no attempts are made to pin memory.
## Shamir Secret Sharing
The `recovery split` / `combine` commands now use the vetted `sharks` crate (GF(2^8)) under the hood, keeping the same CLI and share format (`id-base64`). See docs/SHAMIR.md for details and security notes.
## Mission-ready checklist
- [x] Argon2id + ML-KEM-1024 + XChaCha20-Poly1305 enabled by default
- [x] No GUI, clipboard, or plaintext log exposure
- [x] Cross-platform parity (Windows/macOS/Linux)
- [x] Comprehensive record catalogue with search & tagging
- [x] Lint/tests clean with zero warnings
- [x] Operator docs and threat model committed
For production roll-out, schedule an independent cryptography/code audit and set up fuzzing pipelines (see [`docs/FURTHER_HARDENING.md`](docs/FURTHER_HARDENING.md)).