first commit
This commit is contained in:
97
docs/security-stack/crypto/crypto-hash/src/mac/hmac/hmac.md
Normal file
97
docs/security-stack/crypto/crypto-hash/src/mac/hmac/hmac.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# hmac
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Provides HMAC (Hash-based Message Authentication Code) over SHA-2 variants.
|
||||
HMAC proves that a message was produced by a party in possession of a shared
|
||||
key, giving both data integrity and authenticity guarantees without asymmetric
|
||||
cryptography. This module wraps the audited `@noble/hashes` HMAC primitive
|
||||
and restricts the algorithm surface to the same `HashAlgorithm` union used
|
||||
throughout `@suaveplan/crypto-hash`.
|
||||
|
||||
## Features
|
||||
|
||||
- `hmac(algo, key, data)` — one-shot HMAC-SHA-{256,384,512}
|
||||
- Throws `HashError("HASH.ALGORITHM.UNSUPPORTED")` for unrecognised algorithm strings
|
||||
- Passes through RFC 4231 HMAC-SHA-256 test vectors
|
||||
- Deterministic: same `(algo, key, data)` triple always produces the same tag
|
||||
- Zero runtime state; safe for concurrent use
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { hmac } from "@suaveplan/crypto-hash/mac";
|
||||
import { toHex } from "@suaveplan/crypto-hash/encoding";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const key = encoder.encode("super-secret-key");
|
||||
const data = encoder.encode("payment:amount=100");
|
||||
|
||||
const tag = hmac("SHA-256", key, data);
|
||||
console.log(toHex(tag)); // 32-byte hex string
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { hmac } from "@suaveplan/crypto-hash/mac";
|
||||
import { toHex, fromHex } from "@suaveplan/crypto-hash/encoding";
|
||||
|
||||
// Verify a webhook signature in constant time
|
||||
function verifyWebhookTag(
|
||||
secret: Uint8Array,
|
||||
payload: Uint8Array,
|
||||
receivedTagHex: string
|
||||
): boolean {
|
||||
const expected = hmac("SHA-256", secret, payload);
|
||||
const received = fromHex(receivedTagHex);
|
||||
if (expected.length !== received.length) return false;
|
||||
let diff = 0;
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
diff |= expected[i] ^ received[i];
|
||||
}
|
||||
return diff === 0;
|
||||
}
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
const secret = encoder.encode("webhook-secret");
|
||||
const body = encoder.encode('{"event":"charge.succeeded"}');
|
||||
const tag = toHex(hmac("SHA-256", secret, body));
|
||||
console.log(verifyWebhookTag(secret, body, tag)); // true
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `hmac(algo: HashAlgorithm, key: Uint8Array, data: Uint8Array): Uint8Array`
|
||||
|
||||
Computes the HMAC of `data` under `key` using the specified SHA-2 algorithm.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| `algo` | `HashAlgorithm` | `"SHA-256"`, `"SHA-384"`, or `"SHA-512"` |
|
||||
| `key` | `Uint8Array` | Shared secret key (any length ≥ 1 byte) |
|
||||
| `data` | `Uint8Array` | Message to authenticate |
|
||||
|
||||
**Returns:** Tag bytes — 32 / 48 / 64 bytes for SHA-256 / SHA-384 / SHA-512
|
||||
respectively.
|
||||
|
||||
**Throws:** `HashError("HASH.ALGORITHM.UNSUPPORTED")` if `algo` is not one of
|
||||
the three supported variants.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The internal `hasherFor` helper maps `HashAlgorithm` strings to the corresponding
|
||||
`@noble/hashes` hash constructor. It is a private module function — not exported
|
||||
from this file or from any barrel — so it cannot be called by consumers.
|
||||
This design keeps the public API surface minimal while allowing `hkdf.ts` and
|
||||
`pbkdf2.ts` to import `hasherFor` from this module directly for their own
|
||||
internal use. `argon2id.ts` does not use `hasherFor` because Argon2id is a
|
||||
password-hashing algorithm that accepts its own internal parameterisation rather
|
||||
than a bare hash constructor.
|
||||
|
||||
HMAC output length equals the underlying hash output length. The `@noble/hashes`
|
||||
implementation is constant-time within the hash primitive itself; callers are
|
||||
responsible for constant-time comparison of the resulting tags.
|
||||
Reference in New Issue
Block a user