106 lines
5.2 KiB
Markdown
106 lines
5.2 KiB
Markdown
# @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.
|
||
|
||
<!-- begin:auto-docs -->
|
||
## Documentation tree
|
||
|
||
- [bin](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||
<!-- end:auto-docs --> - [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/bin/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_- [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(no submodules)_ - [hash-password](./src/hash-password/hash-password.md) — <!-- begin:auto-docs --> _(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$<salt>$<hash>
|
||
|
||
# Verify (exit 0 = match, 1 = mismatch)
|
||
$ suaveplan-hash-password --password "correct horse battery staple" \
|
||
--verify '$argon2id$v=19$m=65536,t=3,p=1$<salt>$<hash>'
|
||
$ 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 <n>` (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.
|
||
|