PDFFlare
10 min read

How to Generate a JWT Secret + API Key (Cryptographically Secure)

You're standing up a new service, the README says JWT_SECRET=<your-secret-here>, and the internet's top results suggest you run openssl rand -base64 32or paste 32 random keyboard mashes. The first works but requires a terminal; the second is dangerously low-entropy. There's a middle ground: a one-click random secret generator that uses the same browser CSPRNG that backs WebAuthn and TLS, with presets for the formats your stack expects.

In this guide you'll learn how to generate a JWT secret, an API key, a webhook signing secret, and an AES-256 encryption key online using PDFFlare's Random Secret Generator. The tool works as a jwt secret generator (HS256 / HS384 / HS512), an api key generator online with custom prefixes, a random hex string generator for encryption keys, a webhook signing secret generator (Stripe-style whsec_ format included), a random base64 string generator for libsodium / KMS imports, an encryption key generator online for AES-256 keys, and a general-purpose secure random string generator for any other token need. Generation runs entirely in your browser via crypto.getRandomValues(); nothing is transmitted, logged, or stored.

Why You Need a Cryptographically Secure Random Source

A JWT secret signs every token your auth service issues. If an attacker can guess the secret, they can forge tokens for any user. So “random” isn't a casual property — it's the entire security posture of your authentication system. Two ways people get this wrong:

  • Using Math.random() (or any non-cryptographic PRNG) — these are seeded from system clocks or Mersenne Twister state and produce predictable output. Acceptable for shuffling cards in a game, never for secrets.
  • Using human-typed passwords— “mySecret123!” has maybe 30 bits of entropy because it's drawn from the small set of memorable patterns humans pick. A 256-bit random secret has 256 bits, an unimaginably larger search space.

The right source is a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) seeded from the OS's entropy pool. In a browser that's crypto.getRandomValues(), which delegates to /dev/urandom on Linux/Mac and BCryptGenRandom on Windows. Same standard the browser uses internally for TLS handshakes and WebAuthn key generation.

How to Generate a JWT Secret (Step by Step)

  1. Open the random secret generator. Visit /tools/dev/random-secret-generator.
  2. Click the JWT HS256 secret preset. This sets length to 256-bit and format to base64 — exactly what JOSE-compliant JWT libraries (jsonwebtoken, jose, PyJWT, etc.) expect for HS256. For HS512, click JWT HS512 instead (512-bit base64).
  3. Copy the result. Click the Copy button on the secret output row. The clipboard now holds your production JWT signing secret.
  4. Paste into your secrets manager. For local dev, paste into JWT_SECRET=... in your .env file. For production, drop it into AWS Secrets Manager, GCP Secret Manager, Vercel/Railway env vars, or whatever your platform uses. Never commit the secret to git.

API Key, Webhook Secret, and Encryption Key Workflows

How to generate a secure API key online with a custom prefix

API keys benefit from a recognizable prefix — when a user accidentally pastes one into a chat or commits one to git, a prefix like api_ or sk_live_ makes it scannable. The API key preset produces a 256-bit base64url string with api_ prepended: URL-safe (no +/= chars to escape), prefix-tagged for log scanning, and 256 bits of entropy. Or pick a custom prefix from the Prefix dropdown — Stripe live, Stripe test, GitHub PAT, webhook signing, or roll your own.

How to generate a Stripe webhook signing secret format

Stripe webhook secrets look like whsec_AbCdEfGhIjKl... — a 256-bit value with a whsec_prefix. The Stripe webhook secret preset mirrors this exactly. Pair the result with PDFFlare's HMAC Generator to test that your signing logic produces the same signature Stripe's SDK would. Use the same secret on both ends — your server signs, your receiver verifies, byte-perfect.

How to generate an AES-256 encryption key in hex format

AES-256 needs a 256-bit key (32 bytes). The AES-256 encryption key preset produces 64 hex characters — paste straight into your encryption library, an HSM, KMS import, or a config file expecting hex. If you'd rather have base64 (libsodium prefers it), switch the format to Base64 and the same 32 random bytes encode as ~44 base64 characters with identical entropy.

How to generate multiple API keys in bulk

Beta launches and key rotations need batches. Pick 10, 25, or 50 from the quantity selector and hit Generate — each secret is independently produced from a fresh crypto.getRandomValues() call. Click Copy all to put them all on the clipboard newline-separated; paste into a config file, a database seed, or a CSV ready for import.

Choosing a Format: Hex vs Base64 vs Base64url vs Alphanumeric

Same entropy, different shape — pick the one your downstream tool expects:

  • Hex (lowercase / UPPERCASE) — the most universal format. 2 chars per byte. Used by every CLI (openssl rand -hex, xxd, PowerShell's Get-FileHash) and most crypto libraries when you need a literal hex secret.
  • Base64 — denser (4 chars per 3 bytes). What most JWT libraries expect for HMAC secrets. The + and / chars sometimes need escaping in URLs.
  • Base64url (no padding) — drops = padding and replaces +/ with -_. Safe for URL params, JWT signature segments, and anywhere a regular base64 secret would need escaping.
  • Alphanumeric — A-Z, a-z, 0-9 only. Useful when the secret will pass through systems that mangle symbols. Slightly less entropy per character than base64, but generated with rejection sampling so every char is uniformly distributed (no modulo bias).

Common Mistakes

  • Reusing the same secret across environments. Dev, staging, and prod each need their own JWT secret. If dev leaks, prod stays safe. Different secrets also mean a token signed in dev won't accidentally validate in prod.
  • Committing the secret to git. Even in a private repo, secrets in git history are findable forever. Use .env.local(git-ignored) for dev and a secrets manager for prod. If you accidentally commit one, rotate immediately — assume it's public.
  • Picking a length below the algorithm requirement. HS256 demands 256-bit minimum, HS512 demands 512-bit. The JWT library may not error on a short secret but JOSE validators will, and your security guarantee silently degrades.
  • Mixing up signing and encryption keys. HMAC keys and AES keys are both “random 32 bytes” in shape but should never be reused — the security analysis assumes they're independent. Generate each fresh.

Privacy: Secrets Stay in Your Browser

The whole point of generating secrets in a tool is that the tool can't know what you generated. PDFFlare's random secret generator runs crypto.getRandomValues()in your browser, fills a typed array with cryptographically random bytes, and formats them locally. There's no network call during generation — open DevTools → Network and watch the tab stay empty as you click Generate. The only persisted state is your format / length / prefix preferences in localStorage; generated secrets are NEVER stored. This is what makes the tool safe to use for production secrets, not just dev experiments.

Related Tools

  • HMAC Generator — test that the secret you just generated produces the right webhook / JWT signature. Same algorithms (SHA-256 / 384 / 512), same key, byte-perfect output verified against RFC 4231 reference vectors.
  • JWT Decoder — paste a token signed with your new secret to verify the header.payload structure decodes cleanly and standard claims (iss, sub, exp, iat) are what you expect.
  • UUID Generator — for IDs (request IDs, idempotency keys, primary keys), not for secrets. UUIDs are unique-not-unguessable; secrets are unguessable-not-unique. Different tools.
  • Password Generator — for HUMAN passwords (account login, master passwords). The Random Secret Generator is for SYSTEM secrets that humans never type. Use whichever matches who reads the output.

Wrapping Up

Generating a secure random secret is a 30-second task that decides whether your authentication system can be forged tomorrow. Use a CSPRNG (which PDFFlare's Random Secret Generator uses), pick the format your stack expects, store the secret somewhere your code can reach but a git commit can't, and rotate when in doubt.