Generate Random Bytes
Generate cryptographically secure random bytes for keys, nonces, salts, secrets and API tokens. Up to 4,096 bytes per set and 100 sets at once, as hex, Base64, Base64url, decimal, or ready-to-paste C, Python, JavaScript, Go and Rust literals.
Generated in your browser with crypto.getRandomValues()
How Many Bytes for Keys, Nonces, Salts and Tokens
Every random byte adds 8 bits of unpredictability. These are the sizes the standards ask for; the presets above set them for you.
| Purpose | Bytes | Why that size |
|---|---|---|
| AES-128 key | 16 | The key is exactly 128 bits |
| AES-256 key | 32 | The key is exactly 256 bits |
| AES-GCM nonce (IV) | 12 | NIST SP 800-38D recommends 96-bit IVs |
| ChaCha20-Poly1305 nonce | 12 | RFC 8439 uses a 96-bit nonce |
| HMAC-SHA-256 / JWT HS256 secret | 32 or more | RFC 7518: at least the hash size, 256 bits |
| Password-hash salt | 16 or more | NIST SP 800-132: at least 128 random bits |
| Session ID | 16 is typical | OWASP: at least 64 bits of entropy; 128 leaves a wide margin |
| API key or bearer token | 24 to 32 | Far beyond guessing; 24 bytes is 32 Base64url characters |
A random byte string isn't the same as a password: people can't remember it, and it is meant to be stored by software. For a password, use the random string generator.
Bytes vs Characters: Hex, Base64 and Base64url
The most common mistake with random keys is mixing up bytes and characters. Hex writes each byte as 2 characters. Base64 writes every 3 bytes as 4 characters, padding the end with =. Base64url uses - and _ instead of + and / so it is safe in URLs and file names, and usually drops the padding.
| Bytes | Hex | Base64 | Base64url |
|---|---|---|---|
| 12 | 24 | 16 | 16 |
| 16 | 32 | 24 (ends ==) | 22 |
| 24 | 48 | 32 | 32 |
| 32 | 64 | 44 (ends =) | 43 |
| 64 | 128 | 88 (ends ==) | 86 |
So when a setting asks for "a 32-character key", check what it means. If it decodes hex, 32 characters is only 16 bytes (128 bits). If it uses the characters as they are, 32 hex characters carry 128 bits of randomness, not 256, because each hex character only holds 4 bits. Lengths that are a multiple of 3 bytes (12, 24) never need Base64 padding.
Worked Example: A Secret for JWT HS256
An app signs login tokens with HS256 and the security review says the current secret, mysecret123, is too weak. What should replace it?
Step 1: Minimum size
Step 2: Generate and encode
Step 3: Store it as configuration, not code
Check whether your library decodes the string or uses its text. Some decode Base64 to get the 32 bytes back; many simply use the characters' UTF-8 bytes as the key. Either way the 43 characters carry the full 256 bits, so it's safe, but the two settings are not interchangeable: a token signed by one service won't verify on another that treats the secret differently. Changing the secret signs everyone out, so plan the rotation.
Bytes Ready to Paste Into Code
For test vectors, fixed fixtures or embedded firmware you often want the bytes as a literal rather than a string. Pick a code format and the same bytes are rewritten in that syntax. Here are the same four bytes, de ad be ef, in each:
| Language | Literal |
|---|---|
| C / C++ | unsigned char k[] = { 0xde, 0xad, 0xbe, 0xef }; |
| Python | k = b'\xde\xad\xbe\xef' |
| JavaScript | const k = new Uint8Array([0xde, 0xad, 0xbe, 0xef]); |
| Go | k := []byte{0xde, 0xad, 0xbe, 0xef} |
| Rust | let k: [u8; 4] = [0xde, 0xad, 0xbe, 0xef]; |
Don't commit a real production key as a literal; anything in source control should be treated as public. Literals are for tests and examples. For bit-level practice values rather than whole bytes, use the random binary number generator.
The Same Bytes From a Terminal
Each of these prints 32 random bytes from the operating system's secure generator.
# OpenSSL (Linux, macOS, Git Bash)
openssl rand -hex 32
openssl rand -base64 32
# Linux / macOS without OpenSSL
head -c 32 /dev/urandom | base64
# Python
python3 -c "import secrets; print(secrets.token_hex(32))"
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# Node.js 16 or later
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
# PowerShell 7.2 or later
[Convert]::ToBase64String([Security.Cryptography.RandomNumberGenerator]::GetBytes(32))Note that secrets.token_hex(32) and openssl rand -hex 32 take a byte count and print 64 characters, while token_urlsafe(32) prints 43.
Is It Safe to Make Keys in a Browser?
The randomness is fine. crypto.getRandomValues() is the browser's cryptographically secure generator, seeded by the operating system, and this page creates the bytes on your device without sending them anywhere. The risks come afterwards, from where the value travels:
- Clipboard and screens. Clipboard history, screen sharing and screenshots can all keep a copy. Paste straight into its destination and clear the clipboard.
- Chat and tickets. A key pasted into Slack or an issue tracker should be considered exposed. Share secrets through a secret manager.
- Production keys. Where you can, generate keys inside the system that stores them (a cloud KMS, Vault, or the server's own
openssl) so they never pass through a desktop at all.
One rule matters more than size for AES-GCM: never reuse a nonce with the same key. Reuse lets an attacker recover data and forge messages. With random 12-byte nonces, NIST SP 800-38D limits one key to 2³² (about 4.3 billion) encryptions, so a fresh nonce from here is fine for occasional manual use but your code should generate one per message.
Frequently asked questions
Why does my Base64 output end in = or ==?
Base64 encodes 3 bytes at a time. If the length isn’t a multiple of 3, the last group is padded with one or two = signs. Base64url output here drops them, as JWTs and most URL tokens do.
How is this different from a UUID?
A version 4 UUID is 16 random bytes with 6 bits overwritten to mark the version and variant, leaving 122 random bits, written in a fixed hex format. Raw bytes keep every bit random and let you choose the length and encoding.
Can I get the same bytes again?
No. Nothing is stored or seeded, so copy or download a value before pressing Generate new. Changing only the output format keeps the current bytes.
What is the .bin download for?
It saves the raw bytes, not text, for programs, tests and firmware builds that load a key from a binary file. With several sets, they are joined end to end in one file.
Sources
- MDN: Crypto.getRandomValues(): the browser’s cryptographically secure random generator.
- RFC 4648: The Base16, Base32, and Base64 Data Encodings: Base64, padding, and the URL-safe alphabet.
- RFC 7518: JSON Web Algorithms: section 3.2: HS256 keys must be at least 256 bits.
- NIST SP 800-38D: Galois/Counter Mode (GCM): 96-bit IVs and the 2³² limit for random IVs per key.
- RFC 8439: ChaCha20 and Poly1305: the 96-bit nonce.
- NIST SP 800-132: Password-Based Key Derivation: salts of at least 128 random bits.
- OWASP Session Management Cheat Sheet: at least 64 bits of entropy for session IDs.
- OpenSSL: openssl-rand: the -hex and -base64 options.
- Python documentation: secrets module: token_bytes, token_hex and token_urlsafe.
Related Tools
Create GUIDs for Microsoft and .NET fields.
Generate binary numbers with a chosen bit length.
Create a random pixel image and save it as a PNG.
Pick a date between your chosen start and end dates.
Generate decimals with a chosen range and precision.
Generate fractions and see their simplified forms.