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

4.4 KiB

blake2b

(no submodules)

Purpose

blake2b.ts is the public entry point for the BLAKE2b hash primitive (RFC 7693) in @suaveplan/crypto-hash. BLAKE2b is a fast, secure cryptographic hash function used by Argon2, password-manager keystreams, blockchain-protocol commitments (Zcash, Polkadot), and many other modern protocols. The suaveplan implementation routes through the per-primitive selector layout (blake2b.select.ts) so the noble engine can be replaced without changing caller imports.

The public surface is two symbols: blake2b(message, options) and Blake2bOptions. Variable output length 1..64 bytes covers everything from short MACs (e.g. 16-byte authenticator tags) to full 64-byte digests. Optional key, salt, and personalization parameters mix into the BLAKE2b parameter block as specified by RFC 7693.

Features

  • RFC 7693 compliance — passes the official BLAKE2b-512("abc") known-answer test byte-for-byte.
  • Variable output length — dkLen can be any value in 1..64 (anything outside this range throws HashError(HASH.BLAKE2B_OUTPUT_TOO_LONG)).
  • Optional MAC key — turns the hash into a keyed MAC (BLAKE2b is the only mainstream hash with a built-in MAC mode that does not require an outer HMAC construction). Key length capped at 64 bytes; longer keys throw HashError(HASH.BLAKE2B_KEY_TOO_LONG).
  • Optional 16-byte salt and personalization parameters mix into the parameter block (currently passed through to the noble implementation; not all noble versions surface them, so behaviour is "best-effort honored").
  • Synchronous — blake2b returns a Uint8Array directly. Cheap enough for the hot path.

Usage: Basic Example

import { blake2b } from "@suaveplan/crypto-hash/blake2b";

const digest = blake2b(new TextEncoder().encode("hello world"), { dkLen: 32 });

Usage: Advanced Example

import { blake2b } from "@suaveplan/crypto-hash/blake2b";

// Use BLAKE2b in keyed (MAC) mode for short authenticators.
function authenticate(message: Uint8Array, secret: Uint8Array): Uint8Array {
    if (secret.length > 64) {
        throw new Error("BLAKE2b key must be ≤ 64 bytes");
    }
    return blake2b(message, { dkLen: 16, key: secret });
}

// Domain-separated commitments via the personalization parameter (where
// the underlying engine surfaces it).
function commit(payload: Uint8Array, domain: string): Uint8Array {
    const personalization = new Uint8Array(16);
    personalization.set(new TextEncoder().encode(domain.slice(0, 16)));
    return blake2b(payload, { dkLen: 32, personalization });
}

API Reference

  • blake2b(message: Uint8Array, options: Blake2bOptions): Uint8Array — BLAKE2b hash.
  • Blake2bOptions { dkLen: number; key?: Uint8Array; salt?: Uint8Array; personalization?: Uint8Array } — dkLen is the output length in bytes (1..64).

Errors: HASH.BLAKE2B_OUTPUT_TOO_LONG when dkLen > 64 or dkLen < 1 or dkLen is not an integer; HASH.BLAKE2B_KEY_TOO_LONG when key.length > 64.

Implementation Notes

The selector pattern (blake2b.select.ts) is generated; do not edit it. To add a native engine, place it under impl/blake2b.native/blake2b.native.ts and rerun bun scripts/gen-crypto-selects.ts. The implementation does not validate that salt and personalization are exactly 16 bytes — the noble engine ignores incorrectly-sized buffers rather than throwing, and replicating that behaviour here keeps the surface predictable.