DevToolsmith

Secret Key Generator

Generate cryptographically random secret keys for signing JWTs, API keys, session secrets, webhooks and encryption. Choose the length in bytes and the encoding: hex, Base64, Base64url or plain letters and digits.

Runs 100% in your browser — nothing is uploaded

very strong · 256.0 bits of entropy · time to guess at 100 billion guesses per second (one GPU against a fast hash like MD5): longer than the age of the universe

Recommended key sizes

UseSizeNotes
JWT HS256 secret32 bytes (256 bits)HS384 needs 48 bytes, HS512 needs 64
API key32 bytesBase64url or letters and digits, often with a prefix like sk_live_
Session or cookie secret (Express, Flask, Django)32–64 bytesDjango’s SECRET_KEY defaults to 50 characters
Webhook signing secret (HMAC-SHA256)32 bytesVerify with a constant-time compare
AES-256 key32 bytesUse the raw bytes (decode the hex), not the text
Password-reset or email-verification token16–32 bytesSingle use, short expiry, store a hash

Generating secrets on the command line and in code

Shell
openssl rand -hex 32                     # 64 hex characters
openssl rand -base64 32                  # 44 Base64 characters
head -c 32 /dev/urandom | base64 | tr '+/' '-_' | tr -d '='   # Base64url
Node.js
import { randomBytes } from 'node:crypto';

randomBytes(32).toString('hex');        // JWT secret
randomBytes(32).toString('base64url');  // API key
Python
import secrets

secrets.token_hex(32)        # 64 hex characters
secrets.token_urlsafe(32)    # Base64url, about 43 characters
Go
b := make([]byte, 32)
if _, err := rand.Read(b); err != nil { // crypto/rand
    log.Fatal(err)
}
secret := hex.EncodeToString(b)

Testing a token signed with your new secret? Paste it into the JWT decoder with the secret to verify the signature. Need a password a human will type instead? Use the password generator.

Frequently asked questions

How long should a JWT secret be?

At least as long as the hash output: 256 bits (32 bytes) for HS256, 384 bits for HS384 and 512 bits for HS512 (RFC 7518, section 3.2). Many libraries reject shorter keys. Generate it randomly; a memorable phrase is far weaker than its length suggests, and JWTs signed with weak secrets can be cracked offline from a single token.

Hex, Base64 or Base64url?

All three encode the same random bytes. Hex is the most portable and uses two characters per byte. Base64 is 25% shorter but contains + / and =, which need escaping in URLs and some config files. Base64url swaps those for - and _ and drops the padding, so it can go into URLs, headers and environment variables as is.

How many bits do I need?

128 bits (16 bytes) is already beyond brute force and is enough for session IDs, CSRF tokens and password-reset tokens. Use 256 bits (32 bytes) for long-lived secrets such as API keys, HMAC and JWT signing keys and AES-256 keys. Going beyond 256 bits adds length without practical security.

Is it safe to generate keys in a browser?

The keys come from crypto.getRandomValues, the browser’s cryptographically secure generator, which draws from the operating system’s entropy source like openssl rand does. They are created locally and never sent, stored or put in the URL. For production secrets you can also run one of the commands below on the server where the secret will live, so it never passes through a clipboard.

Should API keys be stored in plain text?

No. Show the key to the user once, then store only a hash of it (SHA-256 is fine because the key is long and random, unlike a password). On each request, hash the presented key and compare. Many services also add a readable prefix like sk_live_ so leaked keys are easy to spot in code and logs.