Files
skills/docs/security-stack/crypto/crypto-utils/src/random/random-bytes/random-bytes.md
2026-05-29 08:20:56 +01:00

2.4 KiB

randomBytes

(no submodules)

Purpose

Produce cryptographically-secure random bytes. Every @suaveplan/crypto-* package routes entropy through this single helper so there is exactly one callsite of globalThis.crypto.getRandomValues to audit, and callers that need deterministic entropy in tests (or a hardware-RNG adapter in production) can swap it with dependency injection rather than monkey-patching globalThis.

Features

  • Wraps globalThis.crypto.getRandomValues (Web Crypto) — works in Node 20+, Bun, browsers, Deno, Cloudflare Workers.
  • Dependency-injectable ByteSource for tests and hardware RNG adapters.
  • Explicit n range check; throws stable CRYPTO.UTILS.RNG.INVALID_LENGTH on bad input.
  • Returns a fresh Uint8Array every call.

Usage: Basic Example

import { randomBytes } from "@suaveplan/crypto-utils/random";

const nonce = randomBytes(12);

Usage: Advanced Example

import { randomBytes, type ByteSource } from "@suaveplan/crypto-utils/random";

// Deterministic source for tests — feeds a known sequence.
function fixedSequence(bytes: Uint8Array): ByteSource {
    let pos = 0;
    return (n) => {
        const out = bytes.slice(pos, pos + n);
        pos += n;
        return out;
    };
}

function generateKey(opts?: { byteSource?: ByteSource }): Uint8Array {
    return randomBytes(32, opts);
}

const testKey = generateKey({
    byteSource: fixedSequence(new Uint8Array(32).fill(0xaa)),
});

API Reference

  • randomBytes(n: number, options?: { byteSource?: ByteSource }): Uint8Array — returns n random bytes. Throws CryptoUtilsError(CRYPTO.UTILS.RNG.INVALID_LENGTH) if n is not a non-negative integer.
  • defaultByteSource: ByteSource — the getRandomValues-backed source. Exported for adapters that want to delegate to it.
  • type ByteSource = (n: number) => Uint8Array — the injection surface.

Implementation Notes

globalThis.crypto is a WHATWG Web Crypto Crypto instance on every supported runtime. In Node we rely on the polyfill injected at test-setup time (node:crypto webcrypto). The test-only byteSource option is deliberately on the call, not a module-level setter, so there is never a case where a test leaks a deterministic source into production code. The length check rejects NaN, non-integers, and negatives — all would previously have been forwarded to getRandomValues, which throws a less-precise RangeError.