Thalhammer / jwt-cpp

A header only library for creating and validating json web tokens in c++
https://thalhammer.github.io/jwt-cpp/
MIT License
864 stars 235 forks source link

EVP_PKEY-based algorithm type #220

Open computerquip-work opened 2 years ago

computerquip-work commented 2 years ago

What would you like to see added?

EVP_PKEY-based algorithm type

Additional Context

It seems like it would be possible to have an algorithm type that's built from an EVP_PKEY directly rather than needing to parse from PEM data (and branching between RSA, ECC, etc). Is there anything preventing such a thing or a reason why that wouldn't be wanted?

prince-chrismc commented 2 years ago

Perhaps this is similar to what you are asking https://github.com/Thalhammer/jwt-cpp/issues/94#issuecomment-1042326701?

computerquip commented 2 years ago

Yep, that's exactly what I'm talking about.

Thalhammer commented 2 years ago

Sorry for the late reply, this completely went under my radar.

Is there anything preventing such a thing or a reason why that wouldn't be wanted?

The most obvious issue is that it requires listing all the possible algorithms somewhere which is not something we currently do. jwt-cpp being a header only library means that every algorithm you don't use wont make it into the final assembly which in it self is a fairly nice property as it saves binary size, compilation time and reduces dependencies. However there is a bigger issue: Composibility. jwt-cpp doesn't restrict the user to a particular algorithm. It does implement the standard ones, but thats more a convenience than a requirement to use them. Every user can implement a custom algorithm of their likeing so there really is no way to have a "list of all algorithms" cause it would be incomplete by definition.

built from an EVP_PKEY directly rather than needing to parse from PEM data (and branching between RSA, ECC, etc)

Ok lets assume we restrict the problem to standard algorithms and put the list in a function (so its not included unless used): How do you distinguish between rsa{256,384,512} and pss{256,384,512} ? They both use RSA keys with the same oid and length with the only difference being the padding algorithm used for signing.

We can (and probably should) change the internal api for the bases classes to accept EVP_PKEY's directly but I don't think theres a way to figure out which algorithm was intended purely based on the pkey. Theres already duplicates (rsa&pss) and I only expect the number of these cases to grow as new algorithms are likely only going to be variations of the existing ones. if you know a clean way to disambiguate them feel free to prove me wrong.

prince-chrismc commented 2 years ago

If we used branching with a limited set of algorithms, It would prevent users from inventing their own algorithms.

The idea of supporting keys more generically is definitely on the road map.

Thalhammer commented 2 years ago

If we used branching with a limited set of algorithms, It would prevent users from inventing their own algorithms.

The idea is not to replace the existing system, but rather to provide a function that constructs one of the existing (standardized) algorithm by providing a key. Basically you put in a 256bit ecdsa key and get back an instance of the ec256 algorithm. I think we could totally support that, with the only issue being that rs and ps use the same key type. So we would need to either default to one of them or skip rsa entirely, both of which don't sound like a good idea to me. Another thing is the question what an empty/nullptr key resolves to. none would be the logical choice, but that sounds like a perfect recipe for security issues to me.

TLDR: We could autodetect the HS, ES, Ed families and either RS or PS*.