1. 28

  2. 19

    Reprising from HN:

    In cryptography, we have a concept of “misuse resistance”. Misuse-resistant cryptography is designed to make implementation failures harder, in recognition of the fact that almost all cryptographic attacks, even the most sophisticated of them, are caused by implementation flaws and not fundamental breaks in crypto primitives. A good example of misuse-resistant cryptography is NMR, nonce-misuse resistance, such as SIV or AEZ. Misuse-resistant crypto is superior to crypto that isn’t. For instance, a measure of misuse-resistance is a large part of why cryptographers generally prefer Curve25519 over NIST P-256.

    So, as someone who does some work in crypto engineering, arguments about JWT being problematic only if implementations are “bungled” or developers are “incompetent” are sort of an obvious “tell” that the people behind those arguments aren’t really crypto people. In crypto, this debate is over.

    I know a lot of crypto people who do not like JWT. I don’t know one who does. Here are some general JWT concerns:

    • It’s kitchen-sink complicated and designed without a single clear use case. The track record of cryptosystems with this property is very poor. Resilient cryptosystems tend to be simple and optimized for a specific use case.

    • It’s designed by a committee and, as far as anyone I know can tell, that committee doesn’t include any serious cryptographers. I joked about this on Twitter after the last JWT disaster, saying that JWT’s support for static-ephemeral P-curve ECDH was the cryptographic engineering equivalent of a “kick me” sign on the standard. You could look at JWT, see that it supported both RSA and P-curve ECDH, and immediately conclude that crypto experts hadn’t had a guiding hand in the standard.

    • Flaws in crypto protocols aren’t exclusive to, but tend to occur mostly in, the joinery of the protocol. So crypto protocol designers are moving away from algorithm and “cipher suite” negotiation towards other mechanisms. Trevor Perrin’s Noise framework is a great example: rather than negotiating, it defines a family of protocols and applications can adopt one or the other without committing themselves to supporting different ones dynamically. Not only does JWT do a form of negotiation, but it actually allows implementations to negotiate NO cryptography. That’s a disqualifying own-goal.

    • JWT’s defaults are incoherent. For instance: non-replayability, one of the most basic questions to answer about a cryptographic token, is optional. Someone downthread made a weird comparison between JWT and Nacl (weird because Nacl is a library of primitives, not a protocol) based on forward-security. But for a token, replayability is a much more urgent concern.

    • The protocol mixes metadata and application data in two different bag-of-attributes structures and generally does its best to maximize all the concerns you’d have doing cryptography with a format as malleable as JSON. Seemingly the only reason it does that is because it’s “layered” on JOSE, leaving the impression that making a pretty lego diagram is more important to its designers than coming up with a simple, secure standard.

    • It’s 2017 and the standard still includes X.509, via JWK, which also includes indirected key lookups.

    • The standard supports, and some implementations even default to, compressed plaintext. It feels like 2012 never happened for this project.

    For almost every use I’ve seen in the real world, JWT is drastic overkill; often it’s just an gussied-up means of expressing a trivial bearer token, the kind that could be expressed securely with virtually no risk of implementation flaws simply by hexifying 20 bytes of urandom. For the rare instances that actually benefit from public key cryptography, JWT makes a hard task even harder. I don’t believe anyone is ever better off using JWT. Avoid it.

    1. 3

      I wrote this because I kept reading “don’t use JWT” and getting pushback with “so what should we use instead?” Hopefully now I can point to this.

      I hope the idea of “single purpose single implementation JWT library” catches on more widely. It would really be much better as just HMAC-SHA256.

      1. 3

        It’s important to note that my experiment is not JWT. When you reduce JWT to a thing that is secure, you give up the “algorithm agility” that is a proud part of the specification.

        This part rang true for me. JWT is in use on one project at work (because others pushed for it). It is used in the most basic sense though. The backend generates all the JWT tokens, and validates the tokens – allowing only the one hmac algo we specify (HS256). The frontend just treats them like opaque tokens.

        I presume we ticked a box somewhere that said “we use JWT”.

        1. 1

          We are using JWT also but I saw that there is a security problem and restricted them to a specific algorithm server side. Basically they become a signed JSON payload, which is fine for our purposes.

        2. 1

          What are your general thoughts on Macaroons? I always liked the model better and seems to be just chained hmacs.

          1. 1

            never heard of them!

        3. 2

          Nice writeup.

          I want to post a public key and have users send me encrypted messages with it

          Also consider client certificates if you can – perfect for server/server communication.

          I want to send some data and have users send it back to me and verify that it hasn’t been tampered with

          Usually we don’t, and when we do: JWT is still not the way I’d recommend doing it. Most implementations lack basic things like an audit trail, and as soon as you add one, you’re left wondering why you needed the user to hold anything besides a cookie anyway.