# @suaveplan/crypto-bin - Suaveplan crypto bins: suaveplan-hash-password (Argon2id / blake2b password hash + verify CLI). Lives in its own package so the universal @suaveplan/crypto does not pull in @suaveplan/cli runtime deps. ## Summary Suaveplan password-hashing CLI. Ships the `suaveplan-hash-password` binary — Argon2id (default) and BLAKE2b password hashing + verification with PHC/MCF-formatted output strings, distinct exit codes per failure class, and an env-injected output adapter so the core is testable without subprocess spawn. This package lives separately from `@suaveplan/crypto` so the universal crypto façade does not pull CLI runtime deps into browser/server consumers that just want primitives. ## Documentation tree - [bin](./src/bin/hash-password.md) — _(no submodules)_ - [hash-password](./src/bin/hash-password.md) — _(no submodules)_ - [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_ - [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_ - [hash-password](./src/bin/hash-password.md) — _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_- [hash-password](./src/bin/hash-password.md) — _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_- [hash-password](./src/bin/hash-password.md) — _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_- [hash-password](./src/bin/hash-password.md) — _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_ - [hash-password](./src/hash-password/hash-password.md) — _(no submodules)_ ## Quickstart ```bash # Hash a password (Argon2id by default) $ suaveplan-hash-password --password "correct horse battery staple" $argon2id$v=19$m=65536,t=3,p=1$$ # Verify (exit 0 = match, 1 = mismatch) $ suaveplan-hash-password --password "correct horse battery staple" \ --verify '$argon2id$v=19$m=65536,t=3,p=1$$' $ echo $? 0 ``` ## Algorithms - **`--algo argon2id`** (default) — OWASP 2023-recommended password hash. Output prefix `$argon2id$v=19$...`. - **`--algo blake2b`** — opt-in alternative for environments that need it. Output prefix `$blake2b$v=1$...`. Cost factor is configurable via `--cost-factor ` (1–31). The verify mode auto-detects the algorithm from the stored hash's prefix, so callers do not have to track which algorithm was used at hash time. ## Exit codes | Code | Meaning | |------|------------------------------------------------------------| | 0 | Success / verify matched | | 1 | Verify mismatch (wrong password) | | 2 | Bad arguments (missing/malformed flag value) | | 3 | Unknown algorithm (unrecognised `--algo` or stored prefix) | | 4 | Verify failed (stored hash is corrupt or unparseable) | The `0` / `1` split matches the de-facto contract for shell pipelines — `if suaveplan-hash-password --password ... --verify ...; then ...; fi` works as expected, with `3+` reserved for operator errors so callers can distinguish "wrong password" from "stored data is broken". ## Programmatic use ```ts import { main } from "@suaveplan/crypto-bin"; const out: string[] = []; const err: string[] = []; const code = main( ["--password", "pw", "--algo", "blake2b", "--cost-factor", "10"], { write: (s) => out.push(s), writeError: (s) => err.push(s), }, ); if (code === 0) { storeHash(out.join("").trim()); } ``` The `main()` function never throws — every error path is captured and surfaced via `env.writeError(...)` and a non-zero return value. See `src/hash-password/hash-password.md` for the full contract. ## Public surface - `main` — testable CLI core. - `parseArgs` — pure argv parser (throws `HashPasswordCliError`). - `detectAlgo` — algorithm sniffer for stored hashes. - `HashPasswordCliEnv` — output adapter interface. - `HashPasswordCliError` — error class wrapping the stable code registry. - `HASH_PASSWORD_CLI_CODES` — `BAD_ARGS` / `UNKNOWN_ALGO` / `VERIFY_FAILED`. ## Dependencies - `@suaveplan/crypto-hash` — Argon2id + BLAKE2b primitives. - `@suaveplan/error` — `SuaveplanError` base + stable code registry. - `@suaveplan/types` — shared cross-package contracts. No dependency on `@suaveplan/cli` — argv parsing is hand-rolled (~40 lines) so the bin stays small.