Cryptographic Key Generator, Explained

After reading this you will know what a cryptographically secure random value is, how many bits of entropy you actually need for keys, IVs, salts and tokens, and how to pick an encoding without weakening the key.

What this tool produces

A key generator gives you random bytes, then formats them for you. The bytes come from a CSPRNG, a cryptographically secure pseudo-random number generator. In the browser that is crypto.getRandomValues, which fills a byte array with unpredictable values seeded from the operating system's entropy pool.

The important property is unpredictability. Given every previous output, an attacker cannot guess the next byte with probability better than chance. For a 256-bit key that means each of the 2^{256} possible values is equally likely, and there are about 1.16 \times 10^{77} of them. That number is larger than the count of atoms in the observable universe, which is roughly 10^{80} divided across all matter you will ever touch.

Here is one concrete output. A 128-bit AES key rendered as hex looks like this:

9f86d081884c7d659a2feaa0c55ad015

That is 32 hex characters, because each hex digit encodes 4 bits and 32 \times 4 = 128. The same 16 bytes in Base64 become n4bQgYhMfWWaL+qgxVrQFQ==, which is 24 characters including padding.

When to use random keys, and when not

Use a fresh CSPRNG value for anything that must be unguessable and has no human memory attached to it:

Symmetric key
The secret for AES or ChaCha20. Generate 128 or 256 bits and store it, never type it.
IV or nonce
A per-message value that makes the same plaintext encrypt to different ciphertext. For AES-GCM it is 96 bits (12 bytes).
Salt
A public, unique value mixed into password hashing so identical passwords hash differently. 128 bits is standard.
API token
A bearer secret in a URL or header. 128 to 256 bits, usually Base64url so it survives copy and paste.

Do not generate a key here when the secret must come from a password a human remembers. A password has far less entropy than 128 random bits, so you must stretch it with a slow key derivation function. Use Key derivation: PBKDF2 & HKDF for that. Random generation and password derivation solve different problems.

Never use Math.random for keys, tokens or IVs. It is a fast statistical generator, not a CSPRNG. Its internal state is small and recoverable, so an attacker who sees a few outputs can predict the rest. Only crypto.getRandomValues is safe for security work.

Entropy, and why bigger is not always better

Entropy measures how many equally likely possibilities a value could have taken. For a value built from n independent random bits:

H = n \text{ bits}, \quad \text{possibilities} = 2^{n}

Here H is the entropy in bits and n is the number of random bits generated. A 128-bit key has 2^{128} \approx 3.4 \times 10^{38} possibilities. A 256-bit key has 2^{256} \approx 1.16 \times 10^{77}.

Brute force cost doubles with every added bit. Suppose an attacker checks 10^{18} keys per second, which is optimistic for any real hardware. Trying all 128-bit keys would take about 2^{128} / 10^{18} \approx 3.4 \times 10^{20} seconds, or roughly 10^{13} years, which is a thousand times the age of the universe. So 128 bits is already out of reach.

Going past your algorithm's key size buys nothing. AES-256 uses 256 bits. Feeding it 512 random bits does not help, because the cipher only consumes 256. The extra entropy is discarded. Choose the size the algorithm defines, then stop.

The bar height is the base-10 logarithm of years needed to try every key. Below zero means less than a year (56-bit falls in milliseconds). At 128 bits the value is about 12.8, meaning roughly 10^12.8 years, far past any physical timescale.

Choosing an encoding without losing bits

Encoding changes the characters, not the entropy. The same 16 random bytes carry 128 bits whether you print them as hex or Base64. What changes is the length and which characters appear.

How 16 random bytes (128 bits) look in each encoding
EncodingAlphabet sizeCharacters usedExample length
Hex160-9 a-f32
Base6464A-Z a-z 0-9 + /24
Base64url64A-Z a-z 0-9 - _24
Byte array2560-25516

Hex is the safest for logs and config files because it has no special characters. Base64url replaces + and / with - and _ and drops padding, so it is safe inside URLs and filenames. Plain Base64 can break a URL because / and + get interpreted or percent-encoded. Pick Base64url for tokens that travel in links.

Count the bits, not the characters. A 24-character Base64 string is not stronger than a 32-character hex string when both encode the same 16 bytes. The tool shows the exact bit length so you never have to guess.

A worked example with the default output

Generating a 256-bit key in hex

The demo generates a 256-bit symmetric key and shows it in hex. Follow the arithmetic:

  1. The generator requests 256 bits. Divide by 8 to get bytes: 256 / 8 = 32 bytes.
  2. crypto.getRandomValues fills a 32-byte array, each byte uniform in 0 to 255.
  3. Hex uses 2 characters per byte, so the output has 32 \times 2 = 64 characters.
  4. Verify entropy: 32 bytes at 8 bits each is 32 \times 8 = 256 bits, matching the label the tool prints.

A sample result:

60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752

Count the characters and you get 64. That is a valid AES-256 key. You can paste it straight into AES encryption to encrypt text with AES-GCM.

See how entropy sets the brute-force wall

At 10^18 guesses per second, a 56-bit key falls in about 0.07 seconds, an 80-bit key takes about 38 years, a 128-bit key takes about 10^13 years, and a 256-bit key takes about 10^51 years. Each added bit doubles the time.

Common mistakes

These errors defeat an otherwise strong key.

  • Reusing a nonce. AES-GCM security collapses if you encrypt two messages with the same key and IV. Generate a fresh 96-bit IV for every message, or use a counter that never repeats.
  • Treating a salt as secret. A salt is not a secret. Its only job is to be unique per password so precomputed tables fail. Store it in plaintext next to the hash.
  • Truncating a token to look tidy. Cutting a 256-bit token to 8 characters throws away entropy. Eight Base64url characters carry only 8 \times 6 = 48 bits, which a determined attacker can search.
  • Encoding then re-encoding. Running Base64 output through hex, or vice versa, does not add entropy. It just makes the string longer and easier to mistype.
  • Generating a key from a password directly. A password is low entropy. Stretch it with PBKDF2 or derive from key material with HKDF instead of pasting it as a key.

Frequently asked questions

How many bits should an API token have?

Use at least 128 bits, which is 22 Base64url characters. That gives 2^{128} possibilities, so guessing is infeasible even at billions of attempts per second. 256 bits (43 characters) is a common conservative choice for long-lived tokens.

Is a hex key weaker than a Base64 key?

No. If both encode the same number of random bytes, they carry identical entropy. A 32-character hex key and a 24-character Base64 key both hold 128 bits. The encoding only changes readability and which characters are safe in URLs.

Can I reuse a salt across users?

You can, but you should not. A shared salt lets an attacker attack all your password hashes at once with one precomputed table. Generate a fresh 128-bit salt per password so each hash stands alone.

Why is 256 bits not "twice as secure" as 128 bits?

Because the scale is exponential, not linear. 256 bits is 2^{128} times harder to brute force than 128 bits, not twice. Both are already beyond any physical attack, so the extra bits matter only when the algorithm requires them.

Does the key ever leave my browser?

No. Generation runs entirely with crypto.getRandomValues in your browser, and the bytes are never sent anywhere. Copy the value before you close the page, because it is not stored.