Files
skills/docs/security-stack/crypto/crypto-sodium/src/primitives/crypto-auth/crypto-auth.md
2026-05-29 08:20:56 +01:00

3.3 KiB

primitives/crypto-auth

(no submodules)

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

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:

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.