Files
suaveplan/packages/security-stack/crypto/crypto-bin/README.md
2026-05-27 23:47:53 +01:00

5.2 KiB
Raw Blame History

@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

- [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

# 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

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.