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
ByteSourcefor tests and hardware RNG adapters. - Explicit
nrange check; throws stableCRYPTO.UTILS.RNG.INVALID_LENGTHon bad input. - Returns a fresh
Uint8Arrayevery 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— returnsnrandom bytes. ThrowsCryptoUtilsError(CRYPTO.UTILS.RNG.INVALID_LENGTH)ifnis not a non-negative integer.defaultByteSource: ByteSource— thegetRandomValues-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.