first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# primitives/crypto-auth
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`cryptoAuth` and `cryptoAuthVerify` expose libsodium's `crypto_auth` and `crypto_auth_verify`, which implement a BLAKE2b-based message authentication code (MAC). Unlike HMAC-SHA256, this MAC is built on BLAKE2b — a fast, parallel, modern hash function with a wider security margin than HMAC-MD5 or HMAC-SHA1, and comparable to HMAC-SHA256/512.
MACs are used to verify that a message was produced by a party holding the shared key and has not been tampered with in transit. They differ from signatures in that both parties must hold the same secret key; there is no separate verification key.
## Features
- BLAKE2b-based MAC via `crypto_auth` — 32-byte output, 32-byte key.
- Constant-time verification via `crypto_auth_verify` — resistant to timing-based MAC forgery.
- `cryptoAuthVerify` returns `false` (never throws) for invalid MACs.
- Async — calls `sodiumReady()` internally.
- Deterministic — same key + message always produces the same MAC.
## Usage: Basic Example
```ts
import { cryptoAuth, cryptoAuthVerify } from "@suaveplan/crypto-sodium/primitives/auth";
const key = crypto.getRandomValues(new Uint8Array(32));
const message = new TextEncoder().encode("verify this");
const mac = await cryptoAuth(key, message);
const valid = await cryptoAuthVerify(key, message, mac);
console.log(valid); // true
```
## Usage: Advanced Example
Authenticating API request payloads with a shared secret:
```ts
import { cryptoAuth, cryptoAuthVerify } from "@suaveplan/crypto-sodium/primitives/auth";
const sharedKey = crypto.getRandomValues(new Uint8Array(32));
async function signPayload(payload: Uint8Array): Promise<{ payload: Uint8Array; mac: Uint8Array }> {
const mac = await cryptoAuth(sharedKey, payload);
return { payload, mac };
}
async function verifyPayload(payload: Uint8Array, mac: Uint8Array): Promise<boolean> {
return cryptoAuthVerify(sharedKey, payload, mac);
}
const data = new TextEncoder().encode('{"action":"transfer","amount":100}');
const signed = await signPayload(data);
const ok = await verifyPayload(signed.payload, signed.mac);
```
## API Reference
### `cryptoAuth(key: Uint8Array, message: Uint8Array): Promise<Uint8Array>`
Computes a 32-byte BLAKE2b MAC over `message` with `key`.
**Parameters:**
- `key` — 32-byte authentication key.
- `message` — Arbitrary-length message bytes.
**Returns:** `Promise<Uint8Array>` — 32-byte MAC.
### `cryptoAuthVerify(key: Uint8Array, message: Uint8Array, mac: Uint8Array): Promise<boolean>`
Verifies a MAC in constant time.
**Parameters:**
- `key` — 32-byte authentication key.
- `message` — The message that was authenticated.
- `mac` — 32-byte MAC to verify.
**Returns:** `Promise<boolean>` — `true` if valid, `false` otherwise. Never throws.
## Implementation Notes
`crypto_auth_verify` from libsodium uses constant-time comparison to prevent timing side channels that would otherwise allow an attacker to iteratively learn the correct MAC byte by byte. The `try/catch` in `cryptoAuthVerify` catches structurally malformed inputs (e.g., wrong-length MAC) and maps them to `false` for consistency.
Both functions are async solely because they call `sodiumReady()` — the underlying sodium operations are synchronous once the WASM is initialised.