9

I'm implementing JWT authentication for a new web service and am unsure which asymmetric algorithm to choose. I've searched around and haven't found any consensus or clear recommendations. According to the PyJWT docs there are a few different algorithms to choose from.

I'd like to use an algorithm that is secure (obviously), has low overhead and is future proof. Which algorithm fits the bill?

Anders
  • 64,406
  • 24
  • 178
  • 215
user3607758
  • 93
  • 1
  • 3

4 Answers4

14

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 in alg: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 in alg: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 in alg: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).

user5994461
  • 1,216
  • 3
  • 12
  • 11
  • A pro for ECDSA is signatures are smaller/shorter, assuming the trade-offs fit within your risk profile. Shorter signatures means smaller requests, which can be useful for mobile devices on sub-par networks or with really chatty protocols. – Astra Jun 27 '20 at 21:07
  • Quite a lot modern JWT implementations support Ed25519 (EdDSA) which is not part of the specification, but is probably the best choice today. – Frank Denis Jun 28 '20 at 11:39
  • this should be the accepted answer. – jpbochi Jul 20 '22 at 11:40
6

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:

Sjoerd
  • 28,707
  • 12
  • 74
  • 102
  • 1
    Thanks for your answer. Just a question regarding the performance of RSA vs ECDSA, you mentioned that ECDSA is faster (I'm assuming you mean that it's more efficient and scales better), but I found this other answer that says that the verification performance of ECDSA is not as good as RSA: https://crypto.stackexchange.com/a/3218. Does this in fact mean that using RSA would lead to better performance when signing and verifying tokens? – user3607758 Oct 01 '18 at 08:23
1

RSA is often the algorithm of choice, as it is now rather old and survived going through a lot of scrutiny. You can't go wrong chosing it. The 256 variant is good enough IMO as SHA256 is nowhere near being broken.

If you care about the size of the message, which you likely do in JWT, you may want to use ECC. It allows for significantly shorter signatures while being as secure as RSA in theory. In practice, the problem is in implementation. There have been spiked curves in the past and a lot of problems with implementation such as off-curve attacks. It is more likely for ECC to have mistakes in implementation IMO.

The PS algorithms are based on RSA but apparently are modified to have a reduction proof. I would not give too much stock in the proof and as it is relatively new and more complicated, implementations may have problems. I would not choose these.

So in the end, I would chooose one of these two depending on what level of security you need. ES256 is probably the beter choice for most webapps.

PS: Either way, you should obviously make sure your jwt library is being updated in a timely manner in case there are security related bugfixes.

Peter Harmann
  • 7,728
  • 5
  • 20
  • 28
  • What is a "spiked curve" or an "off-curve attack"? Wikipedia's elliptic curve cryptography article neither contains the word "spiked" nor "off". – Luc Oct 31 '18 at 09:05
  • 1
    @Luc They are attacks related to how exactly these algorithms work. Elliptic curve algorithms uses math based on points on a specific elliptic curve. An off-curve attack is an attack where the attacker chooses such an input, that the points are not on the curve. If he is able to do so (the library does not check and refuse such input), then the attacker is able to use this to break the security in some ways. Spiked curve attack is an attack, where the creator of the curve deliberately chooses a curve, that can be broken. It is strongly suspected NIST curves are spiked by the NSA. – Peter Harmann Oct 31 '18 at 11:16
  • Thanks! It's hard to find anything about off-curve attacks, though. The only paper that seems remotely relevant is [this one](https://eprint.iacr.org/2017/554.pdf), but the vulns presented there (Ctrl+F for CVE) don't seem to be what you described. Do you have an example CVE or other link? – Luc Oct 31 '18 at 12:39
  • @Luc honestly, no. It is an example our tutor gave at a lecture, but I did not hear about a real world exploitation of this. Anyway, it was just an example of possible implementation mistake (not checking input). The larger point is, that RSA by being older would generally have fewer mistakes in implementations, as people got more used to it and everything that could have been done wrong was at some point. – Peter Harmann Oct 31 '18 at 19:57
-2

You should implement your software this way, that you can easily exchange the signing algorithm. Hopefully pyjwt will also support new algorithms, when the are around.

Given that several people are afraid of quantum computers, which are said to be able to break RSA one day, since prime factors generation can be easily parallalized you should consider using an eliptic curve algorithm.

But as the paragraph below states... using a "good" algorithm is usually a bad idea, if it is used the wrong way.

cornelinux
  • 1,993
  • 8
  • 11