UUID Studio

Random Hex Generator

Cryptographic random bytes as hex.

  • 🔒 No data stored or uploaded
  • âš¡ 100% client-side
  • 🆓 Free, no account

Need more than one tool at a time? Open the full Workbench - or press Ctrl+K to jump to any tool.

Hash, HMAC, AES-GCM/CBC + RSA-OAEP, codecs, JWT decoding, UUID v4, and secure random - all client-side. JWTs use Base64URL (three segments), not a single MIME Base64 block - use Decode JWT below, not raw Base64 decode.

About Random Hex Generator

This produces cryptographically secure random bytes and shows them as hexadecimal. The source is crypto.getRandomValues, the same CSPRNG your browser uses for TLS - not Math.random(), whose internal state is recoverable from a handful of outputs and which has no place generating anything that needs to be unguessable.

The length you want follows directly from what the value is for. An AES-128 key is 16 bytes and therefore 32 hex characters; AES-256 is 32 bytes and 64 hex characters. An AES-GCM nonce is 12 bytes, a CBC IV is 16, an HMAC-SHA256 key should be 32, and a session token or API key wants at least 16 bytes - 128 bits - of entropy.

The two-characters-per-byte relationship is where mistakes happen, and they are consequential. A 32-character hex string is 16 bytes, so a config value sized by character count rather than byte count silently gives you AES-128 where you intended AES-256. Crypto libraries then report an unhelpful key-length error, or worse, accept it.

128 bits of randomness is unguessable in any practical sense: there are more possibilities than there are atoms in a small planet, and no amount of computation searches that space. Going beyond 256 bits adds nothing but length, which is why key sizes stop there.

Generation is local, so the value never crosses the network. That said, a key you will use in production is better generated in the environment where it will live - openssl rand -hex 32 in the deployment shell rather than copied out of a browser tab.

How to use the Random Hex Generator

  1. Choose the byte length for what you need: 16 for AES-128 or a CBC IV, 12 for a GCM nonce, 32 for AES-256 or an HMAC key.
  2. Generate, and note that the hex string will be twice as long as the byte count.
  3. Copy the value, and decode it from hex to bytes in your code rather than passing the text as a key.
  4. For a production secret, prefer generating it where it will be used - the openssl snippet below.

Random Hex Generator in code

The same operation this tool performs, in the languages you are most likely to need it.

JavaScript
function randomHex(bytes) {
  return [...crypto.getRandomValues(new Uint8Array(bytes))]
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
}

randomHex(16);   // 32 hex chars - AES-128 key, or a CBC IV
randomHex(32);   // 64 hex chars - AES-256 key, or an HMAC-SHA256 key

// Never Math.random(): its state is recoverable from a few outputs,
// so any "key" built from it is predictable.

// Common sizes
const gcmNonce = crypto.getRandomValues(new Uint8Array(12));
const cbcIv    = crypto.getRandomValues(new Uint8Array(16));
const aes256   = crypto.getRandomValues(new Uint8Array(32));
Node.js
import { randomBytes } from "node:crypto";

randomBytes(32).toString("hex");        // 64 hex characters
randomBytes(32).toString("base64url");  // 43 chars, URL-safe

// Decode a hex key back to bytes - and CHECK the length
const key = Buffer.from(process.env.KEY_HEX, "hex");
if (key.length !== 32) {
  throw new Error(`KEY_HEX must be 64 hex chars (32 bytes), got ${key.length}`);
}

// randomBytes is the CSPRNG; Math.random() is not. There is no
// situation where Math.random() is the right choice for a key.
Command line - the right way for production
# Hex - the length is in BYTES, output is twice that
openssl rand -hex 32          # 64 chars = 32 bytes = AES-256 key
openssl rand -hex 16          # 32 chars = 16 bytes = AES-128 key / IV
openssl rand -hex 12          # 24 chars = 12 bytes = GCM nonce

# Base64, if you prefer compactness
openssl rand -base64 32

# Straight from the kernel CSPRNG
head -c 32 /dev/urandom | xxd -p -c 32

# Generate secrets where they will be used, not in a browser tab.

When you need this

  • Generating an AES key or IV for a config file or a secret store.
  • Creating an HMAC signing secret for webhook verification.
  • Producing a session token, API key or CSRF token.
  • Making a random test fixture with a known byte length.
  • Generating a salt where a library does not do it for you.

Common problems and what causes them

Hex character count mistaken for byte count
Two hex characters is one byte. 32 hex characters is a 16-byte key, so a value sized by character count gives AES-128 where AES-256 was intended. Always specify and check length in bytes.
Passing the hex string as the key
Handing a 64-character hex string directly to a cipher creates a 64-byte key from the ASCII characters, not the 32 bytes they represent. Decode hex to bytes first - and validate the resulting length.
Using Math.random() or a non-crypto PRNG
Math.random(), Python's random module and similar generators have recoverable internal state, so their output is predictable from earlier values. Use crypto.getRandomValues, randomBytes, secrets or /dev/urandom.
Reusing a nonce or IV
Random bytes are only safe if you generate fresh ones per operation. Reusing a GCM nonce with the same key is catastrophic - it leaks plaintext XOR and enables tag forgery. Generate per message, never once at startup.
Missing zero padding when formatting
Byte 0x0a must render as '0a'. Without padStart or %02x it becomes 'a', shifting every subsequent character and producing an odd-length string that decodes to the wrong bytes.
Generating production keys in a browser
The randomness is sound, but a production key pasted from a browser tab has passed through your clipboard and possibly your shell history. Generate it in the environment where it will live.

FAQ

How many hex characters do I need for an AES-256 key?
64. AES-256 needs 32 bytes, and each byte is two hex characters. AES-128 needs 16 bytes and therefore 32 hex characters - which is the pair most often confused.
Is this random enough for cryptographic keys?
Yes. It uses crypto.getRandomValues, the browser's CSPRNG, which is the same source used for TLS. The randomness is not the weak point; where the value is stored and handled afterwards is.
How many bytes should a token be?
16 bytes (128 bits) is unguessable for any practical purpose; 32 bytes is a common and comfortable choice for API keys and signing secrets. There is little reason to exceed 32 - beyond that you are adding length, not security.
Hex or Base64 for a secret?
Hex is easier to count and compare and is conventional for keys; Base64 is about a third shorter for the same bytes. Either is fine - what matters is that both sides agree, and that you decode to bytes before use.
Can I reuse a generated IV or nonce?
No. An IV or nonce must be fresh for every encryption with a given key. Reusing a GCM nonce is a complete break - it exposes the XOR of the plaintexts and lets an attacker forge authentication tags.
Max length?
Up to 4096 bytes per generation (8192 hex characters).

Related reading