SecureRandom unstable
Cryptographically secure randomness: random bytes, uniform integers, shuffles, UUIDv4, UUIDv7, and ULIDs.
The SecureRandom service is built from one randomBytes primitive
with make. layerWebCrypto draws from getRandomValues on
the WebCrypto reference. The *Unsafe functions draw synchronously from
globalThis.crypto for code that cannot use a service, such as constructors
and model defaults.
Every operation has a never error channel. A bad size or an empty range is
a defect.
Gotchas
There are no float, boolean, or full-range integer helpers. Insecure random
numbers belong to effect/Random, and a secure bit is randomBytes(1).
Constructors
Creates a SecureRandom service from a secure byte source.
When to use
Use to build the service for a platform integration, a custom runtime, or a seeded test double.
Details
Every operation is derived from randomBytes. Sizes are checked before it
is called, and an exception it throws is a defect. Each service orders its
own UUIDv7s and ULIDs, independently of other services and of the
*Unsafe functions.
Gotchas
randomBytes must return a fresh array of exactly size secure random
bytes. UUID formatting mutates the returned array.
Signature
declare function make(randomBytes: (size: number) => Uint8Array): { readonly intBetween: (min: number, max: number, options?: { readonly halfOpen?: boolean; }) => Effect<number>; readonly randomBytes: (size: number) => Effect<Uint8Array<ArrayBufferLike>>; readonly shuffle: <A>(elements: Iterable<A>) => Effect<Array<A>>; readonly ulid: Effect<string>; readonly uuidV4: UuidGenerator; readonly uuidV7: UuidGenerator;}Example Creating a SecureRandom service
import { Effect } from "effect"import { SecureRandom } from "effect/crypto"
const random = SecureRandom.make((size) => globalThis.crypto.getRandomValues(new Uint8Array(size)))
const bytes = await Effect.runPromise(random.randomBytes(4))bytes.length // => 4Layers
layerWebCrypto
unstableLayer that provides SecureRandom from getRandomValues on the WebCrypto
reference.
Details
Requests above the 65,536-byte getRandomValues limit are filled in chunks.
Only getRandomValues is needed, so the layer also works in insecure browser
contexts, which have no crypto.subtle.
Signature
declare const layerWebCrypto: Layer.Layer<SecureRandom>Models
Generates a UUID as a lowercase, hyphenated string or, with
format: "bytes", the 16 UUID bytes.
Signature
interface UuidGenerator { (options?: { readonly format?: "string"; }): Effect<string>; <Format extends "string" | "bytes">(options: { readonly format: Format; }): Effect<Format extends "bytes" ? Uint8Array<ArrayBufferLike> : string>;}Services
SecureRandom
unstableService that generates cryptographically secure random values.
Details
Every operation is derived from randomBytes. See make.
Signature
declare class SecureRandom extends Shape<"effect/crypto/SecureRandom", { readonly intBetween: (min: number, max: number, options?: { readonly halfOpen?: boolean; }) => Effect<number>; readonly randomBytes: (size: number) => Effect<Uint8Array<ArrayBufferLike>>; readonly shuffle: <A>(elements: Iterable<A>) => Effect<Array<A>>; readonly ulid: Effect<string>; readonly uuidV4: UuidGenerator; readonly uuidV7: UuidGenerator;}, this> { constructor(_: never);}Unsafe
randomBytesUnsafe
unstableSynchronously generates size cryptographically secure random bytes from
globalThis.crypto.
When to use
Use when a service cannot be read, as in constructors and model defaults.
Elsewhere, use the SecureRandom service.
Gotchas
Reads globalThis.crypto directly, so neither the WebCrypto reference nor
a mocked SecureRandom service affects it. A negative or non-integer size
throws a RangeError.
Signature
declare function randomBytesUnsafe(size: number): Uint8ArrayulidUnsafe
unstableSynchronously generates a ULID from Date.now() and globalThis.crypto.
Details
Below the maximum timestamp, every ULID generated in this JS realm (process
or worker) sorts after the previous one, using the monotonic mode described
on the SecureRandom service's ulid. The ordering does not hold across
processes or workers. Consecutive ULIDs reveal their generation order, so
never use them as secrets.
Gotchas
Reads Date.now() rather than the Clock, and globalThis.crypto rather
than the WebCrypto reference. A timestamp can run slightly ahead of
Date.now() when the clock moves back or the random part overflows.
Signature
declare function ulidUnsafe(): stringuuidV4Unsafe
unstableSynchronously generates a UUIDv4 from globalThis.crypto, as a lowercase
hyphenated string or, with format: "bytes", the 16 UUID bytes.
Gotchas
Reads globalThis.crypto directly, so neither the WebCrypto reference nor
a mocked SecureRandom service affects it.
Signature
declare const uuidV4Unsafe: { (options?: { readonly format?: "string"; }): string; <Format extends "string" | "bytes">(options: { readonly format: Format; }): Format extends "bytes" ? Uint8Array<ArrayBufferLike> : string;}uuidV7Unsafe
unstableSynchronously generates a UUIDv7 from Date.now() and globalThis.crypto,
as a lowercase hyphenated string or, with format: "bytes", the 16 UUID
bytes.
Details
Below the maximum timestamp, every UUIDv7 generated in this JS realm
(process or worker) sorts after the previous one, as a string and as bytes,
using the counter described on the SecureRandom service's uuidV7. The
ordering is shared with Model.UuidV7WithGenerate, and does not hold across
processes or workers. Consecutive UUIDv7s reveal their
generation order, so never use them as secrets.
Gotchas
Reads Date.now() rather than the Clock, and globalThis.crypto rather
than the WebCrypto reference. A timestamp can run slightly ahead of
Date.now() when the clock moves back or the counter overflows.
Signature
declare const uuidV7Unsafe: { (options?: { readonly format?: "string"; }): string; <Format extends "string" | "bytes">(options: { readonly format: Format; }): Format extends "bytes" ? Uint8Array<ArrayBufferLike> : string;}