Skip to content

kevinburke/h256only

 
 

Repository files navigation

h256only

Fork of jwt-go that rips out every algorithm except H256. The API is a lot simpler, there are a lot fewer opportunities for vulnerable code, and it's harder to make errors. Read the accompanying blog post.

While the inputs and outputs may resemble JWT, this is explicitly not JWT. Algorithm choice is a deliberate JWT design decision; here, specifying an "alg" parameter in the header is illegal.

Why?

JWT is a bad specification, and a number of libraries have had problems implementing it in the past:

All of these problems are due to a specification that is too complex and algorithms that are difficult to implement. It is likely that JWT libraries will continue to have problems in the future.

Particular to the jwt library, jwt-go forces you to check two different places for a valid token (err == nil and t.Valid), and the Keyfunc is error prone. It also registers a number of hashing methods by default, any one of which could have an error.

If you still need to use a JWT-like thing, you should use exactly one state of the art authenticator (HMAC with SHA256), and exactly one method of specifying which key you want to use (a 256-bit random value, stored as a [32]byte).

Changes from the JWT spec

The only known "typ" parameter for this library is "h256only". All other types will return an error on parse.

The "alg" parameter is illegal, because the only supported algorithm is H256.

Upgrade path

It's possible at some point that someone will create a feasible attack against sha256, the cryptography primitive underlying this library. In that case, you should not continue to use this library; create a new library with a better cryptographic primitive and use that instead.

Differences from jwt-go

This library changed 46 files, added 801 lines and deleted 3131 lines, compared with jwt-go. Considering that lines of code correlate with defects, fewer lines of code decreases the chance of a vulnerability appearing in this library.

Here is a partial list of changes.

  • No attempt is made to validate contents of the Claims object when parsing a token. The API's for validating timestamps have been removed; the API's were confusing, the association between JSON and Javascript may lead people to think the timestamps should be multiplied or divided by 1000 before use, and it's difficult to correctly parse large ints in JSON. If you need to validate exp, iat, or nbf, I suggest storing them in the token in an unambiguous time format like RFC3339, or writing the parsing logic yourself and testing it thoroughly.

  • SigningMethod has been removed (there is only one accepted algorithm)

  • Tokens cannot be invalid - we return an error instead

  • No RSA, ECDSA, or None algorithms.

  • No Parser type

  • The "alg" parameter is illegal. The only allowable "typ" is "h256only"

  • ValidationErrors are gone, every function returns exactly one error. We exit immediately from Parse if there is a failure.

  • All keys are *[32]byte - this allows us to use the type system. There is no need anymore for Keyfunc.

  • TimeFunc is gone.

  • Parse/ParseWithClaims don't also return the token, if err is not nil

  • Code to extract JWT tokens from HTTP requests is gone (there should be exactly one way you can set and get in your own code; implement it yourself)

Packages

No packages published

Languages

  • Go 99.1%
  • Makefile 0.9%