# black-bag
`black-bag` is a zero‑trace, ultra‑secure, CLI‑only vault for high‑risk operators. It ships as a single Rust binary with strict defaults (Argon2id time=10; lanes≥4), ML‑KEM‑1024 cascaded wrapping, XChaCha20‑Poly1305 encryption, and meticulous I/O hygiene (no stdout secrets by default, no temp files, atomic 0600 writes). Cross‑platform (macOS/Linux/Windows).
Core ideas:
- Secrets never go to stdout by default; reveals are TTY‑only unless you consciously opt into unsafe modes.
- Strong crypto: Argon2id → ML‑KEM‑1024 (Kyber1024) → 32‑byte DEK → XChaCha20‑Poly1305 for payload and per‑record secret fields.
- Strict limits and locking: page‑locking (best effort), input caps, constant‑time ops, sanitized errors.
Contents
- Install and Build
- Quick Start
- Operations Guide (day‑to‑day flows)
- CLI Reference (every command + flags, with examples)
- Security Model (short)
- Technology Deep Dive (all primitives, flows, AADs, sidecars)
- Vault Format (types, blobs, limits)
- Configuration (env/feature flags)
- Troubleshooting
## Install and Build
```bash
# From crates.io (recommended)
cargo install --locked black-bagg --features pq
# Local build
cargo build --release
install -m 0755 target/release/black-bag ~/.local/bin/black-bag
black-bag --version
```
Tips:
- Use an encrypted disk; avoid shell history (e.g., `HISTCONTROL=ignorespace`).
- For mission shells, set `BLACK_BAG_HARD_MODE=1` to force TTY‑only and disable unsafe stdout/clipboard overrides.
## Quick Start
```bash
# 1) Initialize vault (256 MiB Argon2 memory)
black-bag init --mem-kib 262144 --argon-lanes auto
# 2) Add a login
black-bag add login --title "Ops" --username phoenix --url https://ops.example --tags mission
# 3) List masked summaries
black-bag list --query ops
# 4) Reveal one record on a TTY
black-bag get <UUID> --reveal # TTY required
# 5) Add a TOTP seed (prefer SHA‑256)
black-bag add totp --issuer GitHub --account you@example --secret-file ./totp.txt --algorithm sha256
black-bag totp code <UUID>
# 6) Rotate wrapping keys after missions
black-bag rotate
# 7) Split recovery material (3‑of‑7)
black-bag recovery split --threshold 3 --shares 7
```
## Operations Guide
### Create and Unlock
- `black-bag init --mem-kib 262144 --argon-lanes auto` prompts for a strong passphrase (≥14 NFKC chars and zxcvbn≥3).
- On first use of commands like `list`, `get`, `add`, the CLI prompts to unlock.
### Add Records (selected families)
- Login: `add login --title "Portal" --username alice --url https://example --tags prod`
- Note: `add note --title "Protocol" --tags red-team` then paste body (Ctrl‑D to end).
- API: `add api --service intel --environment prod --access-key AKIA... --scopes read,write`
- TOTP: `add totp --issuer GitHub --account you@example --secret-file ./secret.txt --algorithm sha256`
- Safer alternative: `printf 'otpauth://...' | black-bag add totp --otpauth-stdin`
- Optional ASCII QR: add `--qr --confirm-qr`.
- SSH/PGP/Recovery: `add ssh|pgp|recovery` then paste private/armored payload; stored encrypted.
### Search and Inspect
- `list` (masked): filter with `--kind`, `--tag`, `--query`, or `--fuzzy`.
- `get <UUID> --reveal` shows secrets on TTY. Clipboard copy requires build feature and `--unsafe-clipboard`.
### Rotation, Passphrase Changes, Migration
- `rotate [--mem-kib N]` refreshes KEM and rewraps DEK (updates header MAC/epoch).
- `passwd [--mem-kib N] [--argon-lanes auto|N] [--rekey-dek]` changes passphrase and optionally rekeys payload DEK.
- `migrate` bumps an older vault to latest on‑disk version and recomputes header MAC.
### Recovery and Backups
- Shamir split: `recovery split --threshold 3 --shares 7` outputs shares and a share‑set ID (commit). Store separately.
- Combine: `recovery combine --threshold 3 --shares 1-<b64>,2-<b64>,3-<b64> [--set-id ...] [--raw]`
- `--raw` emits binary to TTY; otherwise base64.
- Backup check: `backup verify --path ~/.config/black_bag/vault.cbor` validates public integrity sidecar without passphrase.
## CLI Reference (Complete)
Global flags (prefix any subcommand):
- `--unsafe-stdout` – allow secrets to flow to stdout/JSON (default off; prefer TTY)
- `--require-mlock` – require page‑locking or abort
- `--emit <tty|stdout|json>` – preferred output mode for non‑reveal flows (stdout/json require `--unsafe-stdout`)
- `--agent <none|keychain>` – enable keychain agent (feature‑gated)
- `--unsafe-clipboard` – allow copying secrets to clipboard (feature‑gated)
- `--duress` – operate on a separate duress vault file
- Env hard mode: `BLACK_BAG_HARD_MODE=1` forces TTY‑only/clipboard‑off regardless of flags
### init
Initialize a new vault.
```
black-bag init --mem-kib <KiB> [--argon-lanes auto|N]
```
Args:
- `--mem-kib` (default 262144; min 32768)
- `--argon-lanes` `auto` (CPU cores capped 8, min 4) or integer ≥4
### add
Add records in families. Sensitive values are captured by prompt/stdin/file; never argv.
Common options: `--title <str>` `--tags <t1,t2>` `--notes <str>`
Families:
- `login` – `--username <str>` `--url <str>`
- `contact` – `--full-name <str>` `--emails <e1,e2>` `--phones <p1,p2>`
- `id` – `--id-type <str>` `--name-on-doc <str>` `--number <str>` `--issuing-country <str>` `--expiry <YYYY-MM-DD>` (secret via prompt)
- `note` – paste body after prompt (Ctrl‑D to finish)
- `bank` – `--institution <str>` `--account-name <str>` `--routing-number <str>` (account number via prompt)
- `wifi` – `--ssid <str>` `--security <str>` `--location <str>` (passphrase via prompt)
- `api` – `--service <str>` `--environment <str>` `--access-key <str>` `--scopes <s1,s2>` (secret key via prompt)
- `wallet` – `--asset <str>` `--address <str>` `--network <str>` (secret key via prompt)
- `totp` – `--issuer <str>` `--account <str>` `--secret-file <PATH>` `--secret-stdin` `--otpauth-stdin` `--qr --confirm-qr` `--digits 6..8` `--step <secs>` `--skew <steps>` `--algorithm <sha1|sha256|sha512>`
- `ssh` – `--label <str>` `--comment <str>` then paste private key
- `pgp` – `--label <str>` `--fingerprint <str>` then paste armored private key
- `recovery` – `--description <str>` then paste recovery payload
Examples:
```
black-bag add login --title "Ops" --username alice --url https://ops --tags prod
black-bag add note --title "Protocol" --tags red-team
black-bag add totp --issuer GitHub --account you@example --secret-file ./secret.txt --algorithm sha256
```
### list
```
black-bag list [--kind <family>] [--tag <tag>] [--query <text>] [--fuzzy]
```
Families: `login, contact, id, note, bank, wifi, api, wallet, totp, ssh, pgp, recovery`
### get
```
black-bag get <UUID> [--reveal] [--clipboard]
```
Notes: `--reveal` requires TTY; `--clipboard` requires feature + `--unsafe-clipboard` and auto‑clears.
### rotate
```
black-bag rotate [--mem-kib <KiB>]
```
### doctor
```
black-bag doctor [--json]
```
Prints ready status, Argon2 params, record count, timestamps, and JSON includes `headerMacVerified`.
### passwd
```
black-bag passwd [--mem-kib <KiB>] [--argon-lanes auto|N] [--rekey-dek]
```
### migrate
```
black-bag migrate
```
### export csv
```
black-bag export csv [--kind <family>] --fields <f1,f2,...> [--include-secrets] --unsafe-stdout
```
Common fields: `id,kind,title,tags,summary,username,url,password,secret_key,totp_secret`
### backup verify
```
black-bag backup verify --path <vault.cbor>
```
### recovery split / combine
```
black-bag recovery split --threshold <n> --shares <m> [--duress]
black-bag recovery combine --threshold <n> --shares <id-b64,...> [--set-id <base32>] [--raw] [--duress]
```
### totp code
```
black-bag totp code --id <UUID> [--time <unix>]
```
### selftest
```
black-bag selftest
```
## Security Model (Short)
- KDF: Argon2id (time=10; lanes≥4, capped 8). Passphrase policy: NFKC, ≥14 chars, uniqueness, zxcvbn≥3.
- Wrapping: ML‑KEM‑1024 public key + ciphertext. Decapsulation secret sealed with KEK.
- Payload & secret fields: XChaCha20‑Poly1305 AEAD with distinct AADs; per‑record rDEKs for secrets at rest.
- Header integrity: keyed BLAKE3 MAC over critical header fields; verified on unlock (constant‑time compare).
- Public integrity sidecar: Blake3 tag keyed by KEM public to detect bit‑rot without secrets.
- Anti‑rollback: header epoch + `.epoch` sidecar (warn/fail); optional keychain epoch pin (feature‑gated) to fail on rollback.
- Process hardening: no coredumps; tracer/ptrace protections; release `panic=abort`; sanitized errors by default.
- Windows ACL: refuse insecure vault directory (Everyone/Authenticated Users write).
References: `docs/CRYPTO_POLICY.md`, `docs/THREAT_MODEL.md`, `docs/SECURITY_MODEL.md`, `docs/VAULT_FORMAT.md`.
Documentation map:
- Full CLI reference: `docs/CLI_REFERENCE.md`
- Technology deep dive: `docs/TECHNOLOGY.md`
- Vault format: `docs/VAULT_FORMAT.md`
- Security model (narrative): `docs/SECURITY_MODEL.md`
- Configuration: `docs/CONFIGURATION.md`
- Crypto policy: `docs/CRYPTO_POLICY.md`
- Threat model: `docs/THREAT_MODEL.md`
## Configuration
- Env vars: `BLACK_BAG_VAULT_PATH`, `BLACK_BAG_VAULT_DURESS_PATH`, `BLACK_BAG_UNSAFE_STDOUT`, `BLACK_BAG_REQUIRE_MLOCK`, `BLACK_BAG_EMIT`, `BLACK_BAG_AGENT`, `BLACK_BAG_UNSAFE_CLIPBOARD`, `BLACK_BAG_DURESS`, `BLACK_BAG_HARD_MODE`, `BLACK_BAG_STRICT_ROLLBACK`, `BLACK_BAG_ALLOW_ROLLBACK` (see docs for details).
- Features: default `mlock`, `pq`; optional `tui`, `agent-keychain`, `clipboard`, `fuzzing`.
## Troubleshooting
- “vault not initialized” → run `init` or set `BLACK_BAG_VAULT_PATH`.
- “header integrity check failed” → stop; header was altered (rollback/tamper). Restore last known good.
- Windows “insecure vault directory permissions” → restrict ACL to current user only.
- TOTP QR warn → requires `--confirm-qr`.
- Clipboard unavailable → not compiled or `--unsafe-clipboard` not set.
## Mission‑Ready Checklist
- [x] Argon2id + ML‑KEM‑1024 + XChaCha20‑Poly1305 enabled by default
- [x] TTY‑only reveals; no stdout secrets by default
- [x] Strict input caps; atomic writes; zeroized buffers
- [x] Cross‑platform (macOS/Linux/Windows)
- [x] Comprehensive record families; search/tagging
- [x] Tests green; warnings denied
- [x] Operator docs + threat model
For production roll‑out, schedule an independent audit and set up long‑run fuzzing (see `docs/FURTHER_HARDENING.md`).
## Recent Security Changes
- Removed CLI secret parameters (prompt/stdin/file only)
- Constant‑time Shamir GF operations; sanitized errors
- Migrated to ML‑KEM‑1024; runtime size checks
- Input bounds added (pre/post parse caps)
- Argon2 defaults increased (time=10; lanes auto≥4)