Signing Algorithms¶
In a signed JWT (a JWS in compact form), the integrity of the token ultimately comes down to the signature. The alg header parameter tells verifiers which signing algorithm was used so they can verify the signature correctly.
This page explains the most common algorithm families, the trade-offs between them, and how to pick a reasonable default. If you want more context about how alg, kid, and other header fields fit into a token, see: JWT Content.
At a high level there are two categories:
- Symmetric algorithms (HMAC): one shared secret is used for both signing and verification.
- Asymmetric algorithms (RSA, ECDSA, EdDSA): a private key signs and a public key verifies.
Quick recommendations
- Single service / monolith: start with
HS256and a strong random secret. - Many independent verifiers (microservices, third parties): prefer
Ed25519(orEd448) when available; otherwiseES256; otherwiseRS256.
Symmetric Algorithms (HMAC)¶
HMAC (Hash-based Message Authentication Code) algorithms use a single shared secret key for both signing and verification. This makes them extremely fast and simple, but it also means every verifier must be trusted with the same secret.
Concretely:
- When you sign, you use the shared secret.
- When you verify, you use that same shared secret.
Most Used¶
If you only need one HMAC algorithm, HS256 is the common default.
| Algorithm | Description | Key Type | Security Level |
|---|---|---|---|
| HS256 | HMAC using SHA-256 | Octet Sequence (Shared Secret) | Good |
| HS384 | HMAC using SHA-384 | Octet Sequence (Shared Secret) | Better |
| HS512 | HMAC using SHA-512 | Octet Sequence (Shared Secret) | Best |
Pros & Cons¶
HMAC tends to feel “easy” because there are fewer moving parts, and performance is excellent. The trade-off is operational: distributing the same secret to many verifiers increases the impact of a single compromise.
What HMAC is great at
- Very fast signing and verification
- Small signatures (good for cookies and bandwidth-constrained contexts)
- Minimal key management complexity
What you give up
- Key distribution safety: every verifier that can validate can also forge if compromised
- Non-repudiation: you cannot prove which holder of the secret signed a token
When to use¶
Use HMAC when the token issuer and verifier are the same application (or a tightly controlled cluster where sharing a single secret is acceptable).
Shared secret blast radius
With HMAC, every verifier must know the same secret. If any verifier is compromised, an attacker can forge tokens.
Asymmetric Algorithms¶
Asymmetric algorithms use a key pair: a private key for signing and a public key for verification. This separates responsibilities cleanly: only the issuer needs the private key, while any number of services can hold the public key.
In practice:
- When you sign, you use the private key (keep it secret).
- When you verify, you use the public key (it can be widely distributed).
This model is usually the right choice when many independent systems must verify tokens, or when you can’t (or don’t want to) trust every verifier with the power to mint tokens.
1. RSA (Rivest–Shamir–Adleman)¶
RSA is the most widely deployed asymmetric option in JWT ecosystems. It’s often chosen for interoperability, especially in enterprise stacks.
RSA has two common flavors in JWT:
- RS* (PKCS#1 v1.5): very widely supported.
- PS* (RSA-PSS): generally considered a more robust padding scheme, but support can be less universal.
| Algorithm | Description | Key Type | Security Level |
|---|---|---|---|
| RS256 | RSASSA-PKCS1-v1_5 using SHA-256 | RSA Key Pair | Good (Standard) |
| RS384 | RSASSA-PKCS1-v1_5 using SHA-384 | RSA Key Pair | Better |
| RS512 | RSASSA-PKCS1-v1_5 using SHA-512 | RSA Key Pair | Best |
| PS256 | RSASSA-PSS using SHA-256 | RSA Key Pair | Stronger than RS256 |
| PS384 | RSASSA-PSS using SHA-384 | RSA Key Pair | Stronger than RS384 |
| PS512 | RSASSA-PSS using SHA-512 | RSA Key Pair | Stronger than RS512 |
RSA choice
Prefer RSA-PSS (PS256) over PKCS#1 v1.5 (RS256) when your ecosystem supports it.
2. ECDSA (Elliptic Curve Digital Signature Algorithm)¶
ECDSA offers comparable security to RSA with much smaller key sizes, which usually yields smaller signatures but is slower.
The main operational footgun with ECDSA is that signing requires a fresh per-signature nonce. High-quality implementations handle this correctly, but nonce reuse (or biased randomness) can leak the private key.
| Algorithm | Description | Key Type | Curve |
|---|---|---|---|
| ES256 | ECDSA using P-256 and SHA-256 | EC Key Pair | P-256 |
| ES256K | ECDSA using secp256k1 and SHA-256 | EC Key Pair | secp256k1 |
| ES384 | ECDSA using P-384 and SHA-384 | EC Key Pair | P-384 |
| ES512 | ECDSA using P-521 and SHA-512 | EC Key Pair | P-521 |
3. EdDSA (Edwards-curve Digital Signature Algorithm)¶
EdDSA is a modern signature scheme designed to avoid common pitfalls (notably, it’s deterministic rather than relying on per-signature randomness like ECDSA).
In SuperJWT, you select a specific EdDSA curve by choosing alg = Ed25519 or alg = Ed448.
Interop note
Some JOSE/JWT ecosystems expose EdDSA as alg = EdDSA with the curve specified elsewhere (for example via key parameters). SuperJWT intentionally uses Ed25519 and Ed448 as algorithm identifiers.
| Algorithm | Description | Key Type | Curve |
|---|---|---|---|
| Ed25519 | EdDSA using Ed25519 curve | OKP (Octet Key Pair) | Ed25519 |
| Ed448 | EdDSA using Ed448 curve | OKP (Octet Key Pair) | Ed448 |
RSA vs ECDSA vs EdDSA¶
If you’re choosing among asymmetric families, it helps to think in terms of interoperability, signature size, and operational risk.
RSA (RS256/PS256)
- âś… Very widely supported; often the safest choice for interoperability.
- ✅ Verification is commonly fast (useful because tokens are usually verified far more often than they’re signed).
- ❌ Signatures are large compared to ECDSA/EdDSA.
- ❌ Prefer
PS256overRS256for new systems when possible; PSS is generally considered more robust and easier to implement correctly.
ECDSA (ES256/ES384/ES512)
- âś… Smaller keys and signatures than RSA for comparable security.
- ❌ Requires high-quality per-signature randomness (a nonce). Bugs or nonce reuse can leak the private key.
- ❌ Verification speed is slower than RSA, especially for ES256K, ES384, and ES512, so verify-heavy workloads may not benefit.
EdDSA (Ed25519/Ed448) 👍👍👍
- âś… Deterministic and compact signatures.
- âś… Fast signing and verification with compact signatures.
- ❌ Support can be uneven in older JWT libraries and SaaS identity products (though it keeps improving).
- ❌ Verification speed is slower than RSA, especially for Ed448, so verify-heavy workloads may not benefit.
Pros & Cons¶
Asymmetric signing is typically what you want once you have multiple verifiers or third-party consumers.
Why teams like asymmetric keys
- You can distribute verification widely without distributing signing power
- Key rotation can be done by publishing public keys (for example via a JWKS endpoint)
- You get a clearer separation of duties between issuer and verifier
What it costs
- More complex key management (rotation, publishing,
kidselection) - Typically larger signatures and slower crypto than HMAC (especially with ECDSA)
When to use¶
Use asymmetric algorithms when any of the following are true:
- You have multiple services verifying tokens (microservices).
- You are issuing tokens to third-party clients (OAuth2/OIDC).
- You cannot trust the verifier with a secret key.
What is best, and why?¶
There isn’t a single "best" algorithm for every deployment. Good defaults depend on who verifies tokens, how painful key distribution is for you, and what your interoperability constraints look like.
These are strong, commonly safe defaults:
- Best default asymmetric:
Ed25519- fast, compact signatures, strong modern design. - Best asymmetric for broad enterprise interoperability:
RS256(orPS256if supported) - widely supported, but larger and slower. - Best symmetric:
HS256- simplest and fastest, but only appropriate when sharing a secret across verifiers is acceptable.
When in doubt, decide based on:
- Who verifies (one service vs many services).
- Interoperability constraints (legacy clients, language runtimes).
- Performance and token size requirements.
Qualitative benchmark (rules of thumb)¶
Real performance depends on hardware and crypto backends, but this table captures the usual trade-offs you can expect.
| Algorithm family | Sign speed | Verify speed | Signature size | Interop |
|---|---|---|---|---|
HMAC (HS256/384/512) |
Fastest | Fastest | Small | Excellent |
EdDSA (Ed25519/Ed448) |
Fast | Fast | Small | Good (improving) |
ECDSA (ES256/384/512) |
Medium | Medium | Small | Good |
RSA-PSS (PS256/384/512) |
Slow | Medium | Large | Medium |
RSA v1.5 (RS256/384/512) |
Slow | Medium | Large | Excellent |
Picking an algorithm by scenario¶
If you just need a "good enough" decision quickly:
- If one service both issues and verifies (or you fully trust every verifier), choose
HS256. - If many services verify and you want to avoid sharing a single secret, choose
Ed25519(orES256). - If you need maximum compatibility with existing JWT consumers, choose
RS256(orPS256if supported). - If you care about small tokens (cookies, mobile), prefer
HS256orEd25519over RSA.
Summary Comparison¶
This is the "shape" of the trade-off:
| Feature | HMAC (Symmetric) | RSA/ECDSA/EdDSA (Asymmetric) |
|---|---|---|
| Keys | Single Shared Secret | Private (Sign) + Public (Verify) |
| Speed | Very Fast | Slower |
| Signature Size | Small | Larger |
| Key Management | Simple (but risky distribution) | Complex (but secure distribution) |
| Best For | Internal Monoliths, Trusted Services | Microservices, Public APIs, OAuth2 |
Security Best Practices¶
Good algorithm choice helps, but most JWT failures in real systems come from configuration mistakes, key leaks, or verification shortcuts.
-
Never accept
noneThe
nonealgorithm produces an unsigned token. That’s almost never what you want for authentication. SuperJWT blocksnoneby default. -
Use strong keys
- HMAC: generate at least 256 bits of randomness (32 bytes) and treat it like a password that must never leak.
- RSA: use at least 2048-bit keys (3072+ is a common upgrade path for long-lived deployments).
-
Protect private keys
Store private keys in a secret manager (Vault, AWS Secrets Manager, etc.) and limit access to only the systems that must sign.
-
Rotate keys deliberately
Plan for rotation from day one: publish (or distribute) verification keys and use
kid(Key ID) to let verifiers select the right key.
Rotation and kid
If you rotate signing keys, publish (or distribute) the current set of verification keys and use kid to let verifiers select the correct key.