black-bagg 0.3.5

Ultra-secure, zero-trace, pure-Rust CLI vault for spies, journalists, and privacy maximalists.
Documentation
black-bagg-0.3.5 has been yanked.

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.

Install

Prerequisites (all OS)

  • Rust toolchain 1.81+ via rustup: https://rustup.rs
  • A C toolchain (C compiler + linker):
    • macOS: xcode-select --install (Xcode Command Line Tools)
    • Debian/Ubuntu: sudo apt update && sudo apt install -y build-essential
    • Fedora/RHEL: sudo dnf groupinstall -y "Development Tools" (or sudo dnf install -y gcc make)
    • Arch: sudo pacman -S --needed base-devel
    • Windows: Install “Build Tools for Visual Studio 2022” with the “Desktop development with C++” workload (MSVC + Windows SDK), then install Rust via rustup (MSVC toolchain)

Install the CLI from crates.io (recommended):

cargo install black-bagg

Upgrade to the latest release:

cargo install black-bagg --force

Note: The installed binary is named black-bag.

Alternatively, build from source (see “Building and testing” below).

Post-Quantum Signatures: ML-DSA-87 (at a glance)

ML-DSA-87 is the NIST-standardized module-lattice digital signature scheme (derived from CRYSTALS-Dilithium, highest-security parameter set). In black-bag it provides authenticity for offline vault backups.

  • What it is: A post-quantum digital signature (Dilithium Level-5). Public key ≈ 2.6 KiB; signatures ≈ 4.6 KiB.
  • What it protects: Ensures a .cbor backup and its keyed integrity tag (.int) came from an authorized signer (no silent tampering).
  • How we use it:
    • We compute a BLAKE3 keyed integrity tag .int over the vault bytes, keyed by the embedded ML‑KEM public key (binds tag to the specific vault state).
    • We sign that tag with ML‑DSA‑87, producing .int.sig.
    • Verification requires both .int and .int.sig with the corresponding ML‑DSA public key.
  • Commands (preferred PQ flow):
    • Generate keys (one‑time):
      • black-bag backup keygen --pub-out backup.mldsa87.pub --sk-out backup.mldsa87.sk
    • Sign a backup:
      • black-bag backup sign --path /path/to/vault.cbor --key backup.mldsa87.sk --pub-out backup.mldsa87.pub
    • Verify before restore/use:
      • black-bag backup verify --path /path/to/vault.cbor --pub-key backup.mldsa87.pub
  • Best practices:
    • Keep backup.mldsa87.sk offline/air‑gapped. Distribute only backup.mldsa87.pub.
    • Always verify both integrity and signature; .int alone only detects bit‑rot.
    • Treat .cbor, .int, and .int.sig as a set; transport them together.

Security Profile (summary)

  • KDF: Argon2id (tunable; default 256 MiB, 3 passes, 1 lane)
  • Key Encapsulation: ML‑KEM‑1024 (Kyber Level‑5)
  • Payload AEAD: XChaCha20‑Poly1305 with domain‑separated AAD
  • PQ Signatures: ML-DSA-87 (Dilithium Level-5) for backup authenticity
  • Memory Hygiene: zeroization everywhere + mlock on Unix (passphrase/DEK/secret buffers)
  • Recovery: Shamir Secret Sharing via unbiased vsss-rs (GF(2^8))
  • Crash Safety: journaled vault commits with atomic roll-forward on restart
  • Zero‑trace UX: no secrets in argv/stdout/logs/tmp; atomic writes with strict perms

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

# initialize a vault (recommended memory cost: 256 MiB)
black-bag init --mem-kib 262144

# add and list API credentials (secrets collected via hidden prompts)
black-bag add api --service intel-api --environment production --access-key AKIA-123 --scopes read,write
black-bag list --kind api

# inspect a record by UUID (safe default: masked; use --reveal on a TTY)
black-bag get <UUID>
black-bag get <UUID> --reveal

Quick start

# 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

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

# 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

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:

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

Command Purpose Notes
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

Comprehensive CLI Details

Below is a complete list of subcommands, flags, and inputs.

Common

  • Global env: BLACK_BAG_VAULT_PATH overrides default vault location.
  • Optional env: BLACK_BAG_AUDIT_LOG appends JSONL authentication events to the given path.
  • Hidden prompts: sensitive values are collected interactively (no echo), never via argv.

Init

  • black-bag init [--mem-kib <KiB>]
    • --mem-kib: Argon2 memory (KiB). Default: 262144 (256 MiB). Minimum: 131072.
    • Prompts: master passphrase (twice).

Add (records)

  • Common flags (all add ):
    • --title <string>
    • --tags <t1,t2,...> (comma separated)
    • --notes <string>
  • Login: black-bag add login [--username <s>] [--url <s>]
    • Prompts: Password: (hidden)
  • Contact: black-bag add contact --full-name <s> [--emails <e1,e2,...>] [--phones <p1,p2,...>]
  • Id: black-bag add id [--id-type <s>] [--name-on-doc <s>] [--number <s>] [--issuing-country <s>] [--expiry <s>]
    • Prompts: Sensitive document secret (optional): (hidden, optional)
  • Note: black-bag add note
    • Prompts: Secure note body (Ctrl-D to finish): (multiline)
  • Bank: black-bag add bank [--institution <s>] [--account-name <s>] [--routing-number <s>]
    • Prompts: Account number / secret: (hidden)
  • Wifi: black-bag add wifi [--ssid <s>] [--security <s>] [--location <s>]
    • Prompts: Wi-Fi passphrase: (hidden)
  • Api: black-bag add api [--service <s>] [--environment <s>] [--access-key <s>] [--scopes <s1,s2,...>]
    • Prompts: Secret key: (hidden)
  • Wallet: black-bag add wallet [--asset <s>] [--address <s>] [--network <s>]
    • Prompts: Wallet secret material: (hidden)
  • Totp: black-bag add totp [--issuer <s>] [--account <s>] [--secret <BASE32>] [--digits <6|7|8>] [--step <seconds>] [--skew <steps>] [--algorithm <sha1|sha256|sha512>]
    • If --secret omitted, prompts: Base32 secret: (hidden)
    • Defaults: --digits 6, --step 30, --skew 1, --algorithm sha1
  • Ssh: black-bag add ssh [--label <s>] [--comment <s>]
    • Prompts: Paste private key (Ctrl-D to finish): (multiline, hidden)
  • Pgp: black-bag add pgp [--label <s>] [--fingerprint <s>]
    • Prompts: Paste armored private key (Ctrl-D to finish): (multiline, hidden)
  • Recovery: black-bag add recovery [--description <s>]
    • Prompts: Paste recovery payload (Ctrl-D to finish): (multiline, hidden)

List / Query

  • black-bag list [--kind <login|contact|id|note|bank|wifi|api|wallet|totp|ssh|pgp|recovery>] [--tag <needle>] [--query <needle>]
    • Outputs masked summaries. Combine filters for precise audits.

Get

  • black-bag get <UUID> [--reveal]
    • Shows metadata; with --reveal on a TTY prints sensitive fields.

Rotate

  • black-bag rotate [--mem-kib <KiB>]
    • Rewraps DEK with fresh randomness; optionally adjust Argon2 memory (min 131072).

Doctor

  • black-bag doctor [--json]
    • Human output or JSON with readiness, Argon2 parameters, passphrase rotation timestamp, and mlock probe results.

TOTP

  • black-bag totp code <UUID> [--time <UNIX-seconds>]
    • Generates a code for a stored TOTP secret; --time allows historic checks.

Backup (integrity + PQ signatures)

  • Keygen (ML‑DSA‑87):
    • black-bag backup keygen --pub-out <path> --sk-out <path>
    • Writes Base64 public key and public||secret concatenated secret blob.
  • Sign:
    • black-bag backup sign --path <vault.cbor> --key <secret-key> [--pub-out <path>]
    • Creates/updates: <vault>.int (BLAKE3 keyed tag) + <vault>.int.sig (ML‑DSA‑87 or Ed25519).
  • Verify:
    • black-bag backup verify --path <vault.cbor> [--pub-key <pub-key>]
    • With --pub-key, verifies both integrity and signature. Without it, checks only bit‑rot.

Self‑test

  • black-bag selftest
    • Runs an encrypt/decrypt round‑trip sanity check.

Version

  • black-bag version
    • Prints version, target, and compiled features (mlock, pq, etc.).

Backup workflow (PQ-safe)

# 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 for assumptions, adversary capabilities, and residual risks. Treat the vault ciphertext as sensitive and keep backups offline.

Building and testing

cargo fmt
cargo clippy --all-targets --all-features
cargo test

Build from source (alternative install)

Prereqs: Rust toolchain 1.81+ (via rustup) and a standard build environment.

git clone <your-repo-url> black-bag
cd black-bag
cargo build --release
install -m 0755 target/release/black-bag ~/.local/bin/black-bag
black-bag --help

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.

Doctor JSON fields

black-bag doctor --json | jq

Emits:

  • ready (bool): overall health flag
  • recordCount (number): number of records
  • argonMemKib, argonTimeCost, argonLanes: Argon2id params
  • createdAt, updatedAt: RFC3339 timestamps
  • passphraseLastRotated: RFC3339 timestamp of the last passphrase rotation
  • mlock.enabled (bool): build/OS support
  • mlock.ok (bool): lock/unlock probe succeeded
  • mlock.error (string|null): OS error if locking failed

Shamir Secret Sharing

The recovery split / combine commands now use the constant-time GF(2^8) backend from vsss-rs, retaining the same CLI and share format (id-base64). See docs/SHAMIR.md for details and security notes.

Configuration

  • BLACK_BAG_VAULT_PATH: override the default vault path. Useful for testing, multiple vaults, or automation.
  • Recommended shell hygiene: HISTCONTROL=ignorespace and avoid pasting secrets into terminals; keep RUST_BACKTRACE=0 in operational shells.

Troubleshooting

  • “mlock: enabled but failed (…)” → Raise OS limits (macOS: check ulimit -l; Linux: ulimit -l 65536 or grant CAP_IPC_LOCK).
  • “Verify failed” on a backup → Stop; do not restore. Recompute .int and re‑verify with the correct .int.sig and public key.
  • “record … not found” → Use black-bag list --query <needle> to locate likely matches, then rerun get.

License

Dual‑licensed under Apache‑2.0 and MIT (your choice). See LICENSE-APACHE and LICENSE-MIT.

Mission-ready checklist

  • Argon2id + ML-KEM-1024 + XChaCha20-Poly1305 enabled by default
  • No GUI, clipboard, or plaintext log exposure
  • Cross-platform parity (Windows/macOS/Linux)
  • Comprehensive record catalogue with search & tagging
  • Lint/tests clean with zero warnings
  • 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).

Instruction Manual

For a polished, cross-platform instruction manual (macOS, Linux, Windows), see:

  • docs/INSTRUCTION_MANUAL.md — professionally formatted manual with installation, operations, backup, and troubleshooting.

The manual covers:

  • Install: prerequisites and cargo install on macOS/Linux/Windows
  • Basic operations: init, add/list/get, search and filters
  • Advanced: rotate, doctor (JSON), totp
  • Recovery: split/combine (Shamir via vsss-rs)
  • Backup and authenticity: ML-DSA-87 keygen/sign/verify workflow
  • Best practices, security considerations, troubleshooting