What Size JWT Secret Do I Need? Key Length Explained
"How long should my JWT secret be?" is one of the most searched JWT security questions. The answer depends on your signing algorithm — but for the vast majority of applications, the answer is simple: 256 bits.
The Short Answer
| Algorithm | Minimum Secret Size | Hex Characters | Bytes |
|---|---|---|---|
| ----------- | --------------------: | ---------------: | ------: |
| HS256 | 256 bits | 64 | 32 |
| HS384 | 384 bits | 96 | 48 |
| HS512 | 512 bits | 128 | 64 |
If you are using HS256 (the most common choice), generate a 256-bit (32-byte) random secret. That is 64 hexadecimal characters.
Why 256 Bits Is Enough
A properly random 256-bit key has 2^256 possible values. Even at a trillion guesses per second, brute-forcing a 256-bit secret would take longer than the age of the universe. NIST recommends a minimum of 128 bits for symmetric keys; 256 bits provides a comfortable security margin.
The real risk is not key length — it is using predictable secrets, reusing secrets across environments, or storing them insecurely.
When to Use 512 Bits
Use a 512-bit secret when:
- You are signing with HS512 (the HMAC block size aligns with 512-bit keys)
- Compliance requirements mandate longer key material
- You want defense-in-depth in high-security or regulated environments
For standard HS256 production use, 512-bit secrets offer no practical security benefit over 256-bit — they just take more storage space.
How to Generate the Right Size
Use the JWT Secret Generator and select the preset that matches your algorithm:
- 128-bit — testing only, never production
- 256-bit — standard production (HS256)
- 512-bit — HS512 or high-security environments
// Node.js: 256-bit secret for HS256
const secret = require('crypto').randomBytes(32).toString('hex');What NOT to Use
- Passphrases or dictionary words ("my-super-secret-key")
- UUIDs or short random strings (< 128 bits)
- Base64-encoded short passwords
- The same secret you use for other purposes (database encryption, API keys)
Bits, Bytes, and Characters Explained
Developers often confuse these units. Here is how they map for hex-encoded secrets:
- 256 bits = 32 bytes = 64 hexadecimal characters
- 512 bits = 64 bytes = 128 hexadecimal characters
When you see a 64-character hex string from the JWT Secret Generator, you have 256 bits of entropy. A 32-character string is only 128 bits — half the recommended minimum for HS256 production use.
Compliance and Industry Guidance
| Standard / Source | Minimum Symmetric Key Size |
|---|---|
| NIST SP 800-131A | 128 bits (112 effective) |
| OWASP JWT Cheat Sheet | 256 bits for HS256 |
| RFC 7518 (JWA) | Key size >= hash output size |
Regulated industries (HIPAA, PCI-DSS, SOC2) often require documented key management procedures. Using 256-bit random secrets satisfies the cryptographic requirement — but auditors also expect rotation policies, access controls, and secrets manager usage. Read how to store JWT secrets securely for storage patterns that satisfy compliance reviews.
Testing Your Key Size in Practice
After generating a secret, sign a test token and verify it:
const jwt = require('jsonwebtoken');
const secret = process.env.JWT_SECRET;
console.log('Secret length (hex chars):', secret.length); // expect 64 for 256-bit
const token = jwt.sign({ test: true }, secret, { algorithm: 'HS256', expiresIn: '5m' });
jwt.verify(token, secret, { algorithms: ['HS256'] }); // throws if invalidPaste the token into the JWT Validator to confirm the signature and inspect the decoded payload. If verification fails, check that your secret has no trailing whitespace or newline characters from copy-paste.
Real-World Scenarios
Startup MVP: 256-bit HS256 secret in platform environment variables. Rotate manually when team members leave.
Growing SaaS: Move to AWS Secrets Manager or Doppler. Automate rotation with the kid header. Keep 256-bit keys — upgrading to 512-bit adds no practical benefit for HS256.
High-security API: HS512 with 512-bit secrets, short token TTL (15 minutes), refresh token rotation, and audience validation on every request.
Verify Your Setup
After generating a secret, sign a test token and verify it with the JWT Validator. Read the full key length comparison for deeper technical detail.
Related Guides
- How to generate a JWT secret — step-by-step walkthrough
- What is a JWT secret key — fundamentals
- JWT best practices checklist — production security
Summary
For HS256 — the default choice for most APIs — use a 256-bit (64-character hex) randomly generated secret. This applies to virtually every web application, mobile backend, and internal service. Upgrade to 512-bit only for HS512 or explicit compliance requirements. The JWT Secret Generator defaults to the correct size for your selected algorithm. When in doubt, choose 256 bits in production. Shorter secrets are the most common cause of offline JWT cracking attacks.
HS256 Deep Dive: Why Key Length Matches the Hash
Spec requirement (RFC 7518)
When developers ask how long a JWT secret should be, the answer for HS256 is remarkably consistent across security standards, JWT libraries, and production best practices: 256 bits of cryptographic entropy, stored as 32 bytes, typically displayed as 64 hexadecimal characters.
That number is not arbitrary. HS256 applies HMAC-SHA256, which uses a 256-bit hash function internally. Matching your secret length to the hash output size ensures you are not the weakest link in the chain. Shorter secrets reduce the search space for offline brute-force attacks; longer secrets add storage overhead without meaningful security gains for this algorithm.
RFC 7518, Section 3.2 states explicitly that a key of the same size as the hash output (256 bits for HS256) or larger MUST be used. This is a specification requirement, not a soft recommendation. Some libraries reject undersized keys; others sign silently and leave you exposed.
This guide explains the bit-byte-character relationship, key validation, and generation in JavaScript, Python, Go, and Java.
Entropy vs visual length
Visual length tells you how many characters appear in a string. Entropy tells you how hard the key is to guess. These diverge whenever a key is derived from human-readable text, truncated hashes, or predictable patterns.
UUID v4 provides roughly 122 bits of randomness—below the HS256 minimum. Base64-encoded 32 bytes looks shorter than hex but carries the same entropy when generated from random bytes. See the HS256 algorithm page and HS256 vs RS256 comparison for broader context.
Generate 256-bit secrets in four languages
Every production secret should come from a cryptographically secure random number generator (CSPRNG)—never from timestamps, usernames, or Math.random(). Store the output in a secrets manager or platform environment variable, not in source code.
const crypto = require('crypto');
const secret = crypto.randomBytes(32).toString('hex'); // 64 chars, 256 bits
process.env.JWT_SECRET = secret;import secrets
hex_secret = secrets.token_hex(32) # 64 hex chars = 256 bitsb := make([]byte, 32)
rand.Read(b)
hexSecret := hex.EncodeToString(b) // 64 charactersSecureRandom random = new SecureRandom();
byte[] bytes = new byte[32];
random.nextBytes(bytes);
String secret = bytesToHex(bytes); // 64 hex charactersAfter generation, sign a test token and verify it with the JWT Validator before deploying to production.
When 512 Bits Makes Sense (and When It Does Not)
HS512 requires 512-bit secrets, but extra length adds no practical benefit for HS256—256 bits already exceeds NIST's 128-bit minimum for symmetric keys. Reserve 512-bit secrets for HS512 or explicit compliance mandates. For typical APIs, HS256 with a 256-bit random secret remains the default; see the JWT secret glossary for review terminology.
Rotating 256-Bit Secrets on Schedule
Key length protects against brute force; rotation limits exposure when secrets leak or staff change. Treat rotation as operational hygiene, not panic response only.
1. Generate a new 256-bit secret via the JWT Secret Generator.
2. Sign new tokens with JWT_SECRET_CURRENT; keep the old value as JWT_SECRET_PREVIOUS.
3. Accept both keys during verification until old tokens expire, then remove the previous secret.
const keys = { '2026-q3': process.env.JWT_SECRET_CURRENT, '2026-q2': process.env.JWT_SECRET_PREVIOUS };
jwt.verify(token, (h, cb) => cb(null, Buffer.from(keys[h.kid], 'hex')), { algorithms: ['HS256'] });Rotate immediately if a secret appears in git history or logs. Schedule routine rotation quarterly or when staff with secret access depart.
Frequently Asked Questions
Is a 32-character password the same as a 256-bit secret?
No. Thirty-two ASCII characters from a human-chosen password contain far less than 256 bits of entropy because the character set is limited and patterns are predictable. A proper HS256 secret requires 32 random bytes, not 32 typed characters.
Should I store my secret as hex or Base64?
Hex (64 characters for 256 bits) is the most common format for JWT_SECRET environment variables—unambiguous and widely supported. Base64URL is shorter and equally valid if all services agree on encoding. Pick one format, document it, and validate at startup.
Can I use the JWT Secret Generator for production keys?
Yes. The JWT Secret Generator uses crypto.getRandomValues() in your browser, so secrets never leave your machine during generation. Copy the output directly into your secrets manager or hosting platform environment configuration.