CIAM Weekly

Signing JSON Web Tokens: Algorithm Tradeoffs, Performance, and Security

Dan Moore's avatar
Dan Moore
Feb 09, 2026
∙ Paid

Heya,

You’ve probably seen RS256, ES256, and EdDSA in your JWT signing libraries. But what do those acronyms actually mean for your application’s security and performance?

I’ve spent way too much time reading specs and RFCs so you don’t have to.

Let’s break down the tradeoffs in plain English. Algorithm choice isn’t academic. It determines how your signatures survive security audits, whether your keys can be recovered from a nonce reuse, and how much bandwidth you burn on every signed token.

Aside: this is not a post about encrypted JWTs, which are also a thing. I’ve only seen one in the wild and am not competent to speak on that kind of JWT.

Algorithm Names

These algorithm names look like cryptographic alphabet soup, but they follow a pattern.

The JOSE (JavaScript Object Signing and Encryption) family defines these algorithms across these RFCs:

  • RFC 7515 - JSON Web Signature (JWS)

  • RFC 7516 - JSON Web Encryption (JWE)

  • RFC 7518 - JSON Web Algorithms (JWA)

  • RFC 8037 - CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE)

RFC 7519 defines JSON Web Tokens but no algorithms. There’s also an authoritative list of algorithms used to sign and encrypt JWTs at the IANA.

As I mentioned above, I’m not going to talk about JWE or encryption below. The JWA RFC defines most of the algorithms while JWS and JWE discuss how to apply them to signing and encrypting.

Most JWS algorithm names follow a two-part pattern: [Signature Algorithm Family][Hash Function].

Let’s break down RS256 as an example:

  • RS: RSASSA-PKCS1-v1_5 (the signature algorithm family)

  • 256: SHA-256 (the hash function’s output size in bits)

So RS256 means: “Use RSASSA-PKCS1-v1_5 signatures with SHA-256 as the hash function.”

Similarly:

  • ES384 = ECDSA with P-384 curve using SHA-384

  • PS512 = RSASSA-PSS using SHA-512

  • HS256 = HMAC using SHA-256

The letter prefix tells you which signature scheme is being used. The number suffix almost always refers to the SHA-2 hash variant.

The Major Algorithm Family Prefixes

Here are the prefixes you might expect to see

  • HS - HMAC with SHA-2 (Symmetric): HS256, HS384, HS512

  • RS - RSASSA-PKCS1-v1_5 (Asymmetric): RS256, RS384, RS512

  • PS - RSASSA-PSS (Asymmetric): PS256, PS384, PS512

  • ES - ECDSA (Asymmetric): ES256, ES384, ES512

  • EdDSA - EdDSA (Asymmetric)

Notice that EdDSA breaks the pattern and doesn’t have a number suffix. You’ll see why shortly.

I also explicitly am omitting the none algorithm. If you aren’t going to sign your JWT, why are you using a JWT at all? Avoid this algorithm which offers a false sense of security.

The Hash Function Number

The number refers to the output size in bits of the SHA-2 hash function:

  • SHA-256: Produces a 256-bit (32-byte) hash

  • SHA-384: Produces a 384-bit (48-byte) hash

  • SHA-512: Produces a 512-bit (64-byte) hash

SHA-256 is excellent for nearly everything. The main reason to use SHA-512 today is performance on 64-bit systems (it can actually be faster) or when you need longer output for specific protocols. The exception: some compliance frameworks require specific hash sizes (FIPS 140-2 at higher security levels may require SHA-384 or SHA-512).

Cryptographic agility (which is the ability to swap algorithms) is generally better than just picking a bigger hash, though.

Never use SHA-1. It’s cryptographically broken. Don’t use it.

Algorithm Families: What Those Letters Mean

Now let’s dive into what each prefix actually signifies and why you might choose one over another.

Hash-based Message Authentication Code

Hash-based Message Authentication Code (HMAC) HMAC is a symmetric message authentication code. The same secret key is used for both signing and verification.

HMAC has the following strengths:

  • provably secure since HMAC has a formal security proof

  • extremely fast, with 5-10 microseconds required per signature, though the exact duration depends on message size and hardware

  • a simple implementation, which is harder to get wrong than asymmetric schemes

  • no random numbers needed: completely deterministic

Nothing is perfect, and the HMAC algorithm has weaknesses too. Key distribution is an issue; both parties need the same secret. Any system component which can verify can also sign so you don’t know which system created a signed JWT. Additionally, key compromise results in total failure; if the key leaks, key holders can forge indefinitely.

These weaknesses are because it is a symmetric signing algorithm.

Known attacks on this algorithm include timing attacks, because naive verification using string comparison can leak information. Always use constant-time comparison (modern libraries do this). Short key attacks, though an implementation detail, affect this algorithm. Using keys shorter than the hash output weakens security and allows for brute forcing. Always use at least a 128 bit key.

Use HMAC algorithms when you control both signer and verifier, such as a set of internal microservices.

Avoid it in the following scenarios:

  • mobile or native apps: keys can be extracted by the client, resulting in compromise

  • third-party API integrations, which lead to key distribution nightmares

  • any system where you are shipping JWTs to uncontrolled systems, which require non-repudiation

HMAC is fast and simple, but its symmetric nature limits applicability. Use only when you control both signer and verifier.

Rivest-Shamir-Adleman (RSA) with PKCS#1 v1.5

RSA with PKCS#1 v1.5 is the original RSA signature algorithm, using the padding scheme from PKCS #1 version 1.5. The “RS” stands for “RSA Signature.” It is an asymmetric algorithm, as are the other algorithms we’ll be looking at from here on.

Asymmetric cryptography means the private key signs the JWT while the public key verifies the signature.

This algorithm is deterministic (the same message always gives the same signature) and doesn’t require random number generation, making implementation simpler than probabilistic schemes.

RS256 has one major advantage over other algorithms below: universal support. Every crypto library and Hardware Security Module (HSM) implements it. This makes it a fit when you need maximum compatibility for an asymmetric algorithm.

However, this algorithm family has drawbacks. Signatures are large (256 bytes for 2048-bit keys, 384 bytes for 3072-bit keys) and signing is slow at 2-10ms per signature depending on key size.

RSA key sizes have specific security implications. 1024-bit RSA was deprecated in 2013 by NIST. 2048-bit RSA provides 112-bit security but is deprecated for use after 2030. It’s best to use 3072-bit RSA or 4096-bit RSA for added security and long-term protection. This assumes classical computing threats. Against quantum computers, RSA is completely broken regardless of key size. ECDSA and EdDSA are also vulnerable to Shor’s algorithm.

Bleichenbacher’s signature forgery attack in 2006 exploited libraries that incorrectly parsed PKCS1-v1.5 padding, allowing attackers to forge signatures. This isn’t a flaw in the algorithm itself, but the algorithm is easy to implement incorrectly.

Rivest-Shamir-Adleman (RSA) with PSS

RSA-PSS is the modern, probabilistic version of RSA signatures. The “PSS” stands for “Probabilistic Signature Scheme”. This uses a more modern, better, padding scheme which has provable security properties. It has been mathematically proven that breaking PSS is at least as hard as breaking RSA.

PS256 and the other PS schemes address the problems with PKCS#1 v1.5. It’s simpler to implement correctly with fewer edge cases than PKCS1-v1.5. There are no known attacks, even theoretical ones, when used with adequate key sizes. You can use existing RSA keys for both RS256 and PS256, and signature sizes are identical to RS256.

However, PS256 is slightly newer. It still uses RSA mathematics, so it has the same performance characteristics: slow signing and large signatures compared to elliptic curve algorithms, which we’ll talk about below. These schemes require a cryptographically secure random number generator for the salt.

Elliptic Curve Signatures

ECDSA (Elliptic Curve Digital Signature Algorithm) uses elliptic curve cryptography.

With ECDSA, the number specifies both the hash function and the elliptic curve. ES256 uses the P-256 (secp256r1) curve with SHA-256. ES384 uses P-384 (secp384r1) with SHA-384. ES512 uses P-521 (secp521r1) with SHA-512. Note that it is P-521, not P-512; it’s easy to make that mistake.

ECDSA offers significant advantages over RSA. Keys are small. A 256-bit elliptic curve (EC) key provides approximately the same security as a 3072-bit RSA key. Raw signatures are tiny at 64 bytes for ES256 compared to 384 bytes for 3072-bit RSA. (ES384 and ES512 produce larger raw signatures.) Both signing and verification are fast, and elliptic curve algorithms have been extensively analyzed since the 1990s. HSM support is excellent across cloud KMS and hardware HSM providers.

The critical weakness with ECDSA is nonce management. The random nonce must be unique for every signature. Reuse a nonce once and you allow private key recovery. This is probabilistic in a bad way. Randomness is critical to this algorithm’s security. This means that implementation complexity is higher than RSA with more moving parts that can go wrong.

If you do reuse a nonce, there’s no brute force required, just algebra. The Sony PlayStation 3 hack in 2010 was a result of this. Sony used a static nonce for all signatures, allowing attackers to recover the private key from two signatures.

Avoid this algorithm if you can’t guarantee cryptographically secure random number generation. In that case, use RSA-PSS or EdDSA instead. ECDSA is the current standard for most applications: fast, small signatures, with excellent HSM support. The nonce management risk is real but manageable with proper libraries.

There’s an alternative, ES256K, that uses uses the secp256k1 Koblitz curve instead of NIST P-256. This curve appears in Bitcoin, Ethereum, and FIDO2 WebAuthn. The NIST curves (P-256, P-384, P-521) were designed by the NSA with unexplained “random” parameters. Some organizations are uncomfortable with this, so Koblitz curves like secp256k1 offer an alternative with transparent genesis.

Not all HSMs and crypto libraries support secp256k1, so if this is of interest, test first.

Edwards-curve Digital Signature Algorithm

EdDSA (Edwards-curve Digital Signature Algorithm) is special, even though it’s another elliptic curve based algorithm.

It doesn’t have a number suffix, just EdDSA. The curve is specified in the key itself, not in the algorithm name. The key specifies which curve via the crv parameter in the JWK.

Two curves are available. Ed25519 provides 128-bit security with 32-byte keys and 64-byte signatures, and is by far the most common. Ed448 provides 224-bit security with 57-byte keys and 114-byte signatures, but is less frequently used.

The critical difference from ECDSA is that the nonce is derived deterministically from the private key and message, not randomly generated. This eliminates the nonce reuse vulnerability entirely. EdDSA is faster than ECDSA at both signing and verification, produces 64-byte signatures like ES256, and was designed from the ground up for side-channel resistance with constant-time implementations. It has formal security proofs with concrete security bounds.

The downsides of this algorithm are practical, not theoretical. The spec is newer (standardized for JOSE in RFC 8037 in 2017). Some JWT libraries don’t fully support EdDSA yet. HSM support is not 100%, but has improved significantly in the last year. AWS KMS added Ed25519 support in November 2025 and Google Cloud KMS supports it. However, Azure Key Vault does not yet support Ed25519. Verify your HSM supports it before committing to this algorithm.

Use EdDSA for new systems with modern infrastructure, performance-critical systems processing millions of signatures per second, and security-paranoid environments. Avoid it when HSM/KMS is required but this algorithm isn’t supported. Also, avoid it when maximum compatibility is needed. EdDSA is technically the best algorithm available, the fastest, most secure and has no nonce reuse vulnerability.

Tradeoffs

Keep reading with a 7-day free trial

Subscribe to CIAM Weekly to keep reading this post and get 7 days of free access to the full post archives.

Already a paid subscriber? Sign in
© 2026 Dan Moore · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture