first commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# primitives/crypto-pwhash
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
`cryptoPwhashStr` and `cryptoPwhashStrVerify` expose libsodium's Argon2id password hashing via `crypto_pwhash_str` and `crypto_pwhash_str_verify`. Argon2id is the winner of the Password Hashing Competition (2015) and the recommended algorithm for password storage by OWASP and NIST SP 800-63B.
|
||||
|
||||
The encoded hash string includes the algorithm identifier, salt, and cost parameters — it is self-contained and safe to store directly in a database. This eliminates a class of bugs where the salt or parameters are stored separately and can become desynchronised.
|
||||
|
||||
## Features
|
||||
|
||||
- Argon2id password hashing via `crypto_pwhash_str` — salt generated internally.
|
||||
- Self-contained encoded output (≈97 chars) — includes algorithm, salt, opsLimit, memLimit.
|
||||
- Constant-time verification via `crypto_pwhash_str_verify`.
|
||||
- Configurable `opsLimit` and `memLimit` — defaults to `OPSLIMIT_INTERACTIVE` / `MEMLIMIT_INTERACTIVE`.
|
||||
- Async — calls `sodiumReady()` internally.
|
||||
- `cryptoPwhashStrVerify` returns `false` on any failure, never throws.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { cryptoPwhashStr, cryptoPwhashStrVerify } from "@suaveplan/crypto-sodium/primitives/pwhash";
|
||||
|
||||
const password = new TextEncoder().encode("user-password-here");
|
||||
const hash = await cryptoPwhashStr(password);
|
||||
|
||||
// Store `hash` in your database. Later, at login:
|
||||
const valid = await cryptoPwhashStrVerify(hash, password);
|
||||
console.log(valid); // true
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
Higher-security settings for sensitive credential storage:
|
||||
|
||||
```ts
|
||||
import { cryptoPwhashStr, cryptoPwhashStrVerify } from "@suaveplan/crypto-sodium/primitives/pwhash";
|
||||
|
||||
const password = new TextEncoder().encode("admin-master-password");
|
||||
|
||||
// Sensitive account — use MODERATE or SENSITIVE preset values
|
||||
// crypto_pwhash_OPSLIMIT_MODERATE = 3, MEMLIMIT_MODERATE = 268435456 (256 MiB)
|
||||
const hash = await cryptoPwhashStr(password, {
|
||||
opsLimit: 3,
|
||||
memLimit: 268_435_456,
|
||||
});
|
||||
|
||||
// Verification automatically reads cost parameters from the hash string
|
||||
const ok = await cryptoPwhashStrVerify(hash, password);
|
||||
|
||||
// Password rehashing: if ok but hash uses lower-cost params, rehash
|
||||
// (the encoded string embeds the params so you can detect this)
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `cryptoPwhashStr(password, opts?): Promise<string>`
|
||||
|
||||
Hashes `password` with Argon2id.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `password: Uint8Array` — Raw password bytes.
|
||||
- `opts.opsLimit?: number` — CPU/iteration cost. Default: `crypto_pwhash_OPSLIMIT_INTERACTIVE`.
|
||||
- `opts.memLimit?: number` — Memory cost in bytes. Default: `crypto_pwhash_MEMLIMIT_INTERACTIVE`.
|
||||
|
||||
**Returns:** `Promise<string>` — Argon2id-encoded hash string, safe for database storage.
|
||||
|
||||
### `cryptoPwhashStrVerify(hash, password): Promise<boolean>`
|
||||
|
||||
Verifies `password` against an encoded hash string.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `hash: string` — Encoded hash from `cryptoPwhashStr`.
|
||||
- `password: Uint8Array` — Candidate password bytes.
|
||||
|
||||
**Returns:** `Promise<boolean>` — `true` if the password matches. Returns `false` (not throws) on any failure including malformed hash strings.
|
||||
|
||||
### `interface PwhashOptions`
|
||||
|
||||
- `opsLimit?: number`
|
||||
- `memLimit?: number`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`crypto_pwhash_str` generates a random salt internally and encodes the full Argon2id parameter set into the output string. This is the `$argon2id$v=19$...` format, compatible with most password-hashing libraries. The salt is never exposed to the caller.
|
||||
|
||||
`crypto_pwhash_str_verify` uses constant-time comparison for the hash check. The `try/catch` maps libsodium exceptions (e.g., malformed hash strings, wrong length) to `false` for uniform API behaviour.
|
||||
|
||||
The interactive preset (`OPSLIMIT_INTERACTIVE`, `MEMLIMIT_INTERACTIVE`) is calibrated for ≈50 ms on typical hardware. Increase `opsLimit` and `memLimit` for stored API keys, encryption master passwords, or recovery codes.
|
||||
Reference in New Issue
Block a user