Recommended asymmetric algorithms for JWT?
The short answer is to use RS256, to be understood as SHA 256 with RSA 2048 bits keys.
See RFC 7518 JSON Web Algorithms (JWA) for all supported algorithms.
On signing algorithms
There are two major signing algorithms supported by JWT: RSA
and ECDSA
.
RSA
(as inalg:RS256
) is the classic asymmetric signing algorithm based on prime factorization. It's very well understood and extremely widely supported. There is no reason to use anything but RSA in my opinion. Recommended key size is 2048 bits.ECDSA
(as inalg:ES256
) is an alternative asymmetric algorithm based on elliptic curves. It started gaining traction in the 2010's as an alternative to RSA. It's not quite as widely supported as RSA but it has some support (notably for SSH keys) and it is growing. It's useful to have two alternatives if one of them turns out to be broken in the future. I don't think there is a point in using ECDSA besides being bleeding edge, because RSA does the job just fine while ECDSA libraries are not as prevalent and have had issues not long ago.
See noteworthy vulnerability CVE-2020-0601 breaking elliptic curves cryptography in all Microsoft products and libraries. In short there was a small bug in the implementation so verifying stuff would verify nothing at all. You will re-use random libraries from the internet to verify JWT tokens in your various applications in various languages, I'd be wary whether libraries can implement ECDSA well when Microsoft and consort couldn't. RSA simply doesn't have this sort of bugs because it's simpler and libraries have been reviewed over decades.
HS256
(as inalg:HS256
): A pre-shared key mode. There is one single key to both sign and verify tokens. The client and the server must both know THE key. I am not aware of any use case for this, so do yourself a favor and ignore HSxxx modes entirely.
On hashing algorithms
There are three major hashing algorithms supported by JWT
: SHA256
, SHA384
and SHA512
.
They have increasing length to resist advances in computing power.
SHA256
is secure enough, it cannot be cracked in a reasonable time with a whole datacenter, there is no reason to favor the stronger slower algorithms.
Note that SHA1
, 160 bits, was never supported in JWT because it was considered insecure and not future proof in the 2010's when JWT was planned.
Performance
When it comes to RSA
vs ECDSA
, there is no general conclusion that can be made on relative performance. Either may be faster than one another.
It's entirely dependent on the library in use and the specific CPU.
One point of having standard tokens it to more easily support authentication across your different applications (Python, Java, C, C#, etc...) using different libraries so it would be really misplaced to make any general conclusion on performance. You should run a benchmark for yourself if you care about performance.
For reference, verifying tokens is in the order of a millisecond broadly speaking (read as: it's much longer than a microsecond and it's much shorter than a second).
Do not confuse password hashing recommendations with JWT recommendations. Most crypto recommendations you will find on the internet (including stack overflow) are oriented toward password hashing (often with one of PBKDFD2/bcrypt/scrypt/argon), that is a use case designed and configured to be slow, possibly up to a whole second to compute a hash. JWT tokens have to verified on every "call" and are meant to be fast enough for API usage.
Key size and robustness
Recommended sizing:
- SHA 256 bits
- RSA with 2048 bits key
- ECDSA with P-256 curve
See RFC 7518 JSON Web Algorithms (JWA) for all supported algorithms.
These are the recommended settings for the 2020-2030 decade. This can resist an attacker dedicating a datacenter to try to crack the key.
Authentication systems (using JWT) are meant to support authentication for external customers on the web and for internal employees in a company. It needs to resist this sort of attack.
Note that all large companies, universities, research centers and government instituations (#NSA) have compute grids at their disposal so it is really "trivial" to procure few thousands servers to brute force a key.
(Recommendations may be revisited in 2030 when AWS/Google will be renting whole datacenters of 60 000 future GPU).
RFC7518 lists the algorithms and whether they are required, recommended or optional for a JWT library. This can help you choose an algorithm that has implementations in other libraries, for interoperability purposes.
From a security perspective, there are these options:
- RSASSA vs. ECDSA. ECDSA use elliptic curves, and some people think these are more secure than RSA. They are also faster and allow you to use smaller keys.
- SHA256, SHA384, SHA512. You could say more is better, but since SHA256 is already impossible to brute-force it makes little sense to use more bits.
- PKCS1-v1_5 vs. PSS. PSS has some security advantages, but is more complex than PKCS1, possibly making implementation errors more likely.
All of these options are secure and the differences are largely theoretical. I would probably recommend ECDSA using P-256 and SHA-256 (alg
parameter value ES256
in the spec), since
- that is likely to be implemented in a lot of JWT implementations, according to the RFC,
- it uses elliptic curves which have some slight security and performance benefits.
The other answer mentioned quantum computers. We don't have viable quantum computers right now, but if they existed they could easily break all of the possible JWT algorithms. So from a post-quantum viewpoint it doesn't matter which one you choose, since all are equally insecure.
See also:
- Is RSASSA-PKCS1-v1_5 a good signature scheme for new systems?
- Should I be using PKCS1 v1.5 or PSS for RSA signatures?