Skip to content

Instantly share code, notes, and snippets.

@paragonie-scott
Last active January 22, 2024 04:20
Show Gist options
  • Save paragonie-scott/e9319254c8ecbad4f227 to your computer and use it in GitHub Desktop.
Save paragonie-scott/e9319254c8ecbad4f227 to your computer and use it in GitHub Desktop.
An Open Letter to Developers Everywhere (About Cryptography)

Hello software developers,

Please check your code to ensure you're not making one of the following mistakes related to cryptography.

I. General Mistakes

II. Symmetric-key Cryptography Mistakes

III. Asymmetric-key Cryptography Mistakes


If you're looking for cryptography right answers, check out the linked gist.

Thank you for your time.

Signed,
A friend who wants your application to be secure

@vdzhuvinov
Copy link

You'll be spared all these problems of home grown solutions if you use standard JOSE and JWT, elegant crypto designed primarily for web and mobile apps :) JOSE stands for JavaScript Object Signing and Encryption, JWT for JSON Web Tokens. For Java and Android check out the Nimbus JWT lib: http://www.connect2id.com/products/nimbus-jose-jwt

@tarcieri
Copy link

@vdzhuvinov there is nothing "elegant" about JOSE and JWT. They had the opportunity to greenfield, but ended up effectively creating JSON-ized SAML full of design mistakes which really shouldn't exist if they had properly studied the attacks on SAML:

  • alg is mandatory for tokens but not for keys: this specifically lead to this class of vulnerabilities which shouldn't exist in modern standards: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ This is practically backwards: alg should be mandatory for keys, and tokens should carry only a kid to associate a token with a particular key, and NEVER carry an alg field (instead kid is optional and alg is mandatory for tokens). This way, the verifier always knows the algorithm, and doesn't need to consult the (malleable) part of the token to infer the algorithm. That's just asking for attacks which trick the verifier into using the wrong algorithm (see earlier mentioned link).
  • Transferring claims between multiple principals (i.e. 3+ principal interactions) are a traditionally difficult problem that leads to ambiguity and confusion (i.e. "confused deputy problem"). With SAML we saw confusion between claims for different principals being misused in the wrong context, "fixed" in SAML 2.0 with AudienceRestrictions. This was carried over in JWT as the aud attribute, but it could've been solved with a cryptographic binding between principals that absolutely ensures claims can't be confused (as seen in e.g. Macaroons). Instead JWT merely carried over SAML's half-solution, and worse, they chose not to make it mandatory, meaning it will not necessarily be automatically checked, so we have two more sharp edges: failure to include an aud attribute leading to attributes being confused in different contexts, and a potential failure to check aud even if it's present. Macaroons, on the other hand, not only cryptographically bind credentials acquired by multiple principals together (i.e. third party caveats / "holder-of-key proofs"), but provide a formal authorization logic for proving them correct.
  • JOSE and COSE did not specify signatures in a way that's interoperable. This is not a problem with other bearer credential formats (e.g. Macaroons) where the tokens can be transcoded between serialization formats and signatures will still verify. COSE couldn't do this due to a lack of forethought on JOSE's part. Anyone who is using JOSE now who wants to transition to COSE must make a wholesale switch: they can't incrementally upgrade.

JOSE is an ugly, design-by-committee standard. It is an unopinionated, one-size-fits-all solution. About the best I can say is that JWE and JWS are better than CMS, but that's not saying much.

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