How long should an HS256 secret be? HMAC key sizes for JWTs

Generate 32 random bytes for HS256 and store them Base64 encoded. A short human secret can be cracked offline from a single token.

RFC 7518 sets a floor for HMAC keys: at least as long as the hash output. That's 256 bits (32 bytes) for HS256, 384 bits (48 bytes) for HS384 and 512 bits (64 bytes) for HS512. Those bytes should come from a secure random generator, not from a word, a phrase or a project name typed into a config file.

By TechCompare · Updated

Topic
HS256 secret length
Secret strength
Category
Best Practices
Settings that keep tokens safe

How this is calculated

An HMAC secret faces an offline attack. Anyone who has one valid token, maybe from their own account, already has a header, a payload and a correct signature. They can try candidate secrets as fast as their hardware allows and know instantly when one matches, with no rate limit and no log entry on your side. Cracking tools like Hashcat ship a JWT mode for exactly this, and secrets like "secret", "changeme" or the app's name fall in seconds. Once found, the secret lets them sign any token they want. A truly random 32-byte key makes that search hopeless. Generate one with openssl rand -base64 32, or with crypto.randomBytes(32) in Node, and load it from a secret store rather than the source code. Many libraries treat a string secret as UTF-8 text, so the Base64 text itself becomes the key. That still works, since it's long and random, but every verifier must use the same reading, either the decoded bytes or the text. The JWT Decoder lets you choose Text or Base64 for the secret, and it warns when a secret is under the RFC minimum for the token's algorithm.

Verdict

Use at least 32 random bytes for HS256 and 64 for HS512, keep the secret out of your repository, and rotate it if it ever appears in a log or a chat. If many services need to verify tokens, consider RS256 or ES256 so only the issuer holds a signing key.

More JWT scenarios

Frequently asked questions

Can I use a password as my JWT secret?
Only a long random one, like the output of a password generator set to its maximum length, and even then raw random bytes are better. A memorable password can be guessed offline from any token it signed.
Is a longer secret slower?
Not in any way you'd notice. HMAC hashes the key once per signature, so a 64-byte secret costs about the same as a 32-byte one.
Should the secret be Base64 or plain text?
Either works if every signer and verifier agrees. Most libraries read a string as UTF-8 text. If yours decodes Base64 first, pick Base64 in the JWT Decoder so it checks the same bytes.