Developer tools · UUID generator
How crypto.getRandomValues Turns 16 Random Bytes Into a v4 UUID
· How it works
uuid cryptography browser-apis
A version 4 UUID is 16 bytes from a cryptographically secure generator with six bits overwritten. This post walks the bytes from the Web Crypto call to the familiar 36-character string.
The ID you need before the server answers — why client-side generation comes up in offline-first forms, optimistic UI and batch imports
An offline form may need an identifier before a server responds, and an optimistic UI may create several objects at once. A UUIDv4 is designed to be generated independently without a central counter. It is not a proof of user identity or a secret you can safely put in place of authentication. If your database needs values that sort by creation time, random v4 IDs are not ordered; that is a separate schema decision rather than a reason to weaken their randomness.
What crypto.getRandomValues actually does — filling a typed array from the operating system's entropy source, not from a JavaScript formula
crypto.getRandomValues fills a Uint8Array with 16 bytes from the browser platform’s cryptographically secure random generator. It does not derive the values from Date.now() or Math.random(). The operating system and browser implement the underlying entropy source, so JavaScript code receives bytes rather than implementing a random-number formula itself. ToolAcre refuses to generate an identifier if its secure source is absent.
Overwriting byte 6 and byte 8 — how the version nibble becomes 4 and the variant bits become 10xx, and why only six bits are lost
RFC 9562 describes a version nibble and a variant field. Starting with sixteen random bytes, set the high four bits of byte 6 to binary 0100 (version 4), and set the top two bits of byte 8 to 10 (the standard variant). The implementation uses (byte6 & 0x0f) | 0x40 and (byte8 & 0x3f) | 0x80. Six bits are overwritten, leaving 122 random bits under the UUIDv4 scheme. Those constant bits do not make the remaining bytes less random.
From bytes to 8-4-4-4-12 — hex encoding, lowercase output and hyphen placement as the standard defines them
Encode each byte as exactly two hexadecimal characters with a leading zero when needed. Insert dashes after 4, 6, 8 and 10 bytes, producing the familiar 8-4-4-4-12 hexadecimal-character groups. A valid v4 string has a 4 at the start of its third group and one of 8, 9, a or b at the start of its fourth. Formatting does not add entropy; it only makes the underlying 128-bit value interoperable with tools that expect the UUID text form.
Worked example — one 16-byte buffer traced through masking and formatting to its final UUID string
Trace the illustrative bytes 00 11 22 33 44 55 F6 77 38 99 AA BB CC DD EE FF. Masking F6 at byte 6 produces 46; masking 38 at byte 8 produces B8. After lowercase hexadecimal formatting and dashes the result is 00112233-4455-4677-b899-aabbccddeeff. This is a deliberately fixed teaching example, not an identifier to reuse in production. Generate a fresh one for each real object and compare the version and variant positions yourself.
crypto.randomUUID() as the one-call shortcut — what the newer method does for you and where it is unavailable
On a secure origin, crypto.randomUUID() performs the v4 generation and formatting in one call. ToolAcre uses it where available and otherwise falls back to getRandomValues with the explicit bit operations above. Browser availability differs by context: randomUUID is restricted to secure contexts, while getRandomValues may still exist on an HTTP LAN page. Neither branch falls back to Math.random merely to keep a button apparently working.
What this does not cover — time-based (v1, v7) and name-based (v3, v5) versions, which need different inputs than random bytes
This mechanism does not describe time-based v1 or v7 identifiers, name-based v3/v5 identifiers, or experimental v8 layouts. Random UUIDs have a very low collision probability with sound randomness, not an absolute mathematical impossibility of collision. A v4 UUID by itself should not be used as an access-control check or password-reset token without considering secrecy, lifetime and authorization independently.
Takeaway: secure randomness is the whole job — the ToolAcre UUID generator draws from the same browser CSPRNG, so what you copy is what your code would produce
Secure randomness is the job. The ToolAcre UUID generator uses the browser’s CSPRNG, enforces version and variant bits and offers a well-formedness check for copied values. Compare a generated result with the byte-layout example, then use the new, unique output only for the role your application actually assigned it.