Skip to content

Instantly share code, notes, and snippets.

@NeilMadden
Created June 4, 2017 10:52
Show Gist options
  • Save NeilMadden/01a338a7d9d53c87b313024bc86d3156 to your computer and use it in GitHub Desktop.
Save NeilMadden/01a338a7d9d53c87b313024bc86d3156 to your computer and use it in GitHub Desktop.
Suggestions for JWT BCP
  1. Explicitly spell out the ECDH-ES public key validation routines from NIST. I have a blog post summarising them: https://neilmadden.wordpress.com/2017/05/17/so-how-do-you-validate-nist-ecdh-public-keys/
  2. Recommend that (despite the -ES) ECDH is safest when both keys are ephemeral (eg you use some initial step to retrieve a fresh authenticated ephemeral key from the other party).
  3. Spell out how to authenticate ECDH ephemeral keys. For instance, include an inner signed JWT that repeats the epk and possibly the apu/apv claims too.
  4. Recommend that the apu and apv claims as a bare minimum include a hash of both public keys and SHOULD include any other known identifiers.
  5. Recommend that the receiving party recalculates the apu and apv claims from known inputs to check they match. (Or leave these out of the JWT and require the other party to recalculate them).
  6. Provide explicit key lifetime requirements. E.g., for AES GCM this should not exceed 2^32 messages for randomly-generated IVs, and not exceed 2^64 blocks in total (so unless you restrict JWT lengths to less than 2^32 blocks and use a message counter as IV then this also limits to 2^32 messages). For CBC it should not exceed 2^48 messages.
  7. Require that the "alg" and "enc" claims are ONLY used to reject unexpected algorithms, NEVER to select an algorithm (even amongst a "supported" set). Cryptographic agility should be achieved by using "kid" claims that reference one of a set of known keys and the key should specify the algorithm (either explicitly or by the key parameters/size).
  8. Deprecate or strongly recommend against all of the RSA encryption modes except OAEP-256.
  9. Strongly discourage any use of compression with encrypted JWEs - it is too easy to leak sensitive information.
  10. Recommend that if a JWE is used to encrypt a password or other value for which knowing the length may be a weakness, that such fields are explicitly padded by the application or at least use CBC mode to reduce the amount of length information leaked to a multiple of the AES block size.
  11. Require constant-time comparisons of HMAC tags.
  12. Recommend using deterministic ECDSA signatures as described in RFC 6979 to minimise the risk of leaking the private key.
  13. Recommend that if the ECDH calculation produces an all-zero shared secret that this is rejected.
  14. Never produce a signed JWT containing a "sub" claim unless you are explicitly vouching for the identity of that subject. It is far too easy to accidentally produce valid OIDC id tokens from unrelated code!

Generally I think all of the RSA usage should be deprecated. JWTs are primarily used for short tokens and RSA adds too much space overhead there and is fraught with peril. Elliptic curve crypto is also fraught with peril, but that peril can be managed by explicitly spelling out the validation required and using ephemeral keys wherever possible.

@NeilMadden
Copy link
Author

For points 3&4, if you make the apu/apv claims contain hashes (thumbprints) of the public keys then you can just include those in the signed part rather than duplicating the whole epk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment