JWT Signing Algorithms Explained
A thorough guide to HS256, RS256, ES256, EdDSA, and more -- how they work, when to use them, and how to migrate between them.
Why the Algorithm Matters
The alg header in a JWT determines how the token's signature is created and verified. Choosing the right algorithm affects your system's security posture, performance, key management complexity, and interoperability. A poor choice can leave your authentication system vulnerable; a good choice can simplify your architecture while keeping it secure.
JWT algorithms fall into three main categories: symmetric (HMAC), asymmetric (RSA, ECDSA, EdDSA, RSA-PSS), and the special case of none (unsecured). This guide covers each family in depth. For the basics of JWT structure, see our What is a JWT? guide.
Algorithm Overview
| Algorithm | Type | Key Size | Signature Size | Recommendation |
|---|---|---|---|---|
| HS256 | Symmetric | 256 bits | 32 bytes | Good for single-server |
| HS384 | Symmetric | 384 bits | 48 bytes | Rarely needed |
| HS512 | Symmetric | 512 bits | 64 bytes | Maximum HMAC security |
| RS256 | Asymmetric (RSA) | 2048+ bits | 256 bytes | Most widely supported |
| RS384 | Asymmetric (RSA) | 2048+ bits | 256 bytes | Higher security margin |
| RS512 | Asymmetric (RSA) | 2048+ bits | 256 bytes | Maximum RSA security |
| ES256 | Asymmetric (ECDSA) | 256 bits | 64 bytes | Recommended default |
| ES384 | Asymmetric (ECDSA) | 384 bits | 96 bytes | Higher security margin |
| ES512 | Asymmetric (ECDSA) | 521 bits | 132 bytes | Maximum ECDSA security |
| PS256 | Asymmetric (RSA-PSS) | 2048+ bits | 256 bytes | Preferred over RS256 |
| EdDSA | Asymmetric (EdDSA) | 256 bits (Ed25519) | 64 bytes | Best overall choice |
| none | Unsecured | N/A | 0 bytes | Never use in production |
HMAC Family: HS256, HS384, HS512
HMAC (Hash-based Message Authentication Code) algorithms are symmetric: the same secret key is used for both signing and verification. This is the simplest JWT algorithm family and the one most developers encounter first.
How HMAC Signing Works
HMAC combines a cryptographic hash function (SHA-256, SHA-384, or SHA-512) with a secret key. The signing process:
signature = HMAC-SHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
secret_key
)Because the same key signs and verifies, anyone who can verify a token can also forge one. This is the fundamental limitation of symmetric algorithms.
When to Use HMAC
- Single-service applications: When the same server (or tightly coupled cluster) both issues and verifies tokens.
- Performance-critical paths: HMAC is significantly faster than asymmetric algorithms for both signing and verification.
- Internal service tokens: When communication is between services you control and sharing a secret is manageable.
Key Requirements
The secret key must be at least as long as the hash output: 256 bits for HS256, 384 bits for HS384, 512 bits for HS512. Use a cryptographically random generator -- never a human-readable password. For example, in Node.js:
const crypto = require('crypto');
const secret = crypto.randomBytes(32).toString('base64');
// Produces a 256-bit random keyRSA Family: RS256, RS384, RS512
RSA algorithms are asymmetric: a private key signs the token and a separate public key verifies it. RS256 (RSA with SHA-256) is the most widely used JWT algorithm across the industry, supported by virtually every JWT library and identity provider.
How RSA Signing Works
RSA signing uses PKCS#1 v1.5 padding with a SHA hash function. The private key (typically 2048 or 4096 bits) creates a digital signature that can be verified using the corresponding public key. The public key can be freely distributed without compromising the private key.
Key Sizes
RSA key sizes have grown over time as computational power has increased:
- 2048 bits: Current minimum recommendation. Considered secure until approximately 2030.
- 3072 bits: Provides a security margin beyond 2030. Recommended for new deployments.
- 4096 bits: Maximum commonly used size. Significantly slower but provides a large security margin.
The main drawback of RSA for JWTs is signature size: RSA signatures are always the same length as the key (256 bytes for a 2048-bit key), making RSA-signed JWTs noticeably larger than those signed with ECDSA or EdDSA.
When to Use RSA
- Maximum compatibility: RS256 is supported by every JWT library, identity provider, and cloud service.
- Distributed verification: Share the public key with all verifying services while keeping the private key secured at the auth server.
- Regulatory compliance: Some compliance frameworks specifically require RSA.
ECDSA Family: ES256, ES384, ES512
ECDSA (Elliptic Curve Digital Signature Algorithm) provides the same security guarantees as RSA but with dramatically smaller keys and signatures. ES256 uses the P-256 curve and provides 128-bit security -- equivalent to a 3072-bit RSA key.
Why ECDSA is Gaining Popularity
- Smaller keys: A 256-bit EC key provides comparable security to a 3072-bit RSA key.
- Smaller signatures: 64 bytes for ES256 vs. 256 bytes for RS256. This directly reduces JWT size.
- Faster key generation: Generating an EC key pair is orders of magnitude faster than RSA.
- Good performance: Signing is faster than RSA; verification is comparable.
The Curves
- ES256: Uses the P-256 (secp256r1) curve. 128-bit security level. The recommended default for most applications.
- ES384: Uses the P-384 (secp384r1) curve. 192-bit security level. Provides a substantial security margin.
- ES512: Uses the P-521 (secp521r1) curve. Note: it is P-521, not P-512 -- the key is 521 bits. 256-bit security level.
Caveats
ECDSA requires a high-quality random number generator during signing. If the random nonce is predictable or reused, the private key can be recovered from the signature. Modern libraries handle this correctly, but it is worth understanding the risk. This is one reason some developers prefer EdDSA, which is deterministic.
RSA-PSS Family: PS256, PS384, PS512
RSA-PSS (Probabilistic Signature Scheme) is an improved version of RSA signing that provides a formal security proof. It uses the same RSA keys as RS256 but a different padding scheme.
PS256 is generally preferred over RS256 for new deployments because:
- It has a provable security reduction to the RSA problem.
- It is not vulnerable to Bleichenbacher-type attacks that affect PKCS#1 v1.5 (used by RS256).
- It uses the same key material, so migrating from RS256 to PS256 only requires a configuration change.
The main limitation is slightly lower library support compared to RS256, though all major JWT libraries now support PSS algorithms.
EdDSA: The Modern Choice
EdDSA (Edwards-curve Digital Signature Algorithm) using the Ed25519 curve represents the state of the art in JWT signing. It was designed to be fast, secure, and resistant to common implementation mistakes.
Advantages of EdDSA
- Deterministic signing: Unlike ECDSA, EdDSA does not require a random nonce during signing. This eliminates an entire class of implementation bugs.
- Performance: Ed25519 is one of the fastest signature algorithms available, outperforming both RSA and ECDSA in signing speed.
- Small keys and signatures: 256-bit keys and 64-byte signatures, comparable to ES256.
- Resistance to side-channel attacks: Ed25519 was designed with constant-time operations to resist timing attacks.
- 128-bit security level: Equivalent to ES256 and RSA-3072.
When to Use EdDSA
EdDSA (Ed25519) is the best default choice for new applications that do not have specific compatibility requirements. It offers the best combination of security, performance, and implementation safety. The only significant limitation is that some older libraries and platforms do not yet support it -- though support is now widespread across all major languages and platforms.
The “none” Algorithm
The JWT specification includes alg: none for unsecured JWTs -- tokens with no signature at all. This was intended for constrained scenarios where integrity is guaranteed by other means (e.g., tokens inside an already-authenticated TLS channel).
In practice, alg: none has been the source of critical vulnerabilities when servers accept it unintentionally. Never accept alg: none in production. Always enforce an explicit algorithm allowlist in your verification code.
For more on this and other common security mistakes, see our JWT Security Best Practices guide.
Performance Comparison
Performance matters for high-traffic APIs that verify JWTs on every request. Here are approximate relative speeds (higher is better):
| Algorithm | Sign Speed | Verify Speed | Token Size Impact |
|---|---|---|---|
| HS256 | Fastest | Fastest | Smallest (+43 bytes) |
| EdDSA | Very fast | Very fast | Small (+86 bytes) |
| ES256 | Fast | Moderate | Small (+86 bytes) |
| RS256 | Slow | Fast | Large (+342 bytes) |
| PS256 | Slow | Fast | Large (+342 bytes) |
For most applications, the performance difference is negligible. Verification speed matters more than signing speed since tokens are verified on every API request but only signed during authentication. RS256 and PS256 have fast verification despite slow signing.
Migration Paths
If you are currently using an older or less secure algorithm, here are recommended migration paths:
- HS256 to ES256 or EdDSA: When moving from a single-server setup to a distributed architecture. This requires generating new key pairs and updating all verifying services.
- RS256 to PS256: The easiest migration. Both use the same RSA keys -- you only need to change the algorithm configuration in your JWT library.
- RS256 to ES256: Provides smaller tokens and better performance. Requires generating new EC keys and distributing the new public key to all verifiers.
- Any algorithm to EdDSA: The recommended direction for greenfield development. Check library support in your language ecosystem before migrating.
During migration, use the JWKS (JSON Web Key Set) pattern with kid (Key ID) headers. Publish both old and new public keys in your JWKS endpoint. Issue new tokens with the new algorithm while continuing to accept tokens signed with the old algorithm until they expire.
Choosing the Right Algorithm
Here is a decision framework:
- Single server, maximum simplicity: HS256 with a strong random secret.
- Distributed system, maximum compatibility: RS256 with 2048+ bit keys.
- Distributed system, modern stack: ES256 with P-256 keys.
- Greenfield, best overall: EdDSA with Ed25519.
- Upgrading from RS256: PS256 (same keys, better security proof).
Inspect Your Token's Algorithm
Use our JWT Decoder to paste any token and instantly see its algorithm, key strength rating, and security recommendations. The security analysis tab identifies weak algorithms and suggests stronger alternatives -- all processed entirely in your browser.
Further Reading
- RFC 7518 — JSON Web Algorithms (JWA)
IETF specification of cryptographic algorithms for JWS and JWE.
- RFC 7515 — JSON Web Signature (JWS)
The standard for digitally signing JSON content.
- NIST Key Management Recommendations
NIST guidelines for cryptographic key sizes and algorithm selection.