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

@wsargent
Copy link

I'd really like references to Keyczar, Kalium, cryptlib or libsodium in there (as well as any other high level crypto libraries in there). Blog post: https://tersesystems.com/2015/10/05/effective-cryptography-in-the-jvm/

Also links to http://saweis.net/crypto.html and https://github.com/sweis/crypto-might-not-suck

@Matir
Copy link

Matir commented Nov 18, 2015

@atoponce:

How is your system any different than using CTR mode with the nonce set to 0? This isn't even a "they are similar" comparison: the output should be identical. Both are AES(0, key) + AES(1, key) + ... + AES(n, key)

@atoponce
Copy link

@Matir:

The only argument is simplicity. AES-ECB(data, key) is simpler than AES-CTR(data, key, counter).

@AntonKueltz
Copy link

Please take a look at Thomas Pornin's post on elliptic curves in regard to your last point on safe curves.

@paj28
Copy link

paj28 commented Nov 19, 2015

I like your post. However, claiming "Not using authenticated encryption" is a mistake is a bit alarmist - "encrypt then MAC" works fine. Also, it might be worth having a separate section for password hashing; Failing to use a salt is another mistake. Personally, I'd remote the "Exception: for the sake of learning" because that actually applies to everything here, not just home-grown ciphers.

@creshal
Copy link

creshal commented Nov 19, 2015

With the PHC over, I'd recommend adding its Argon2 password hashing together with bcrypt.

@atoponce
Copy link

@creshal I wouldn't. Argon2 is new and given the suite of current algorithms, relatively untested and unused. I would let Argon2 bake for at least 5 years before giving it considerable attention for production use. We need mathematicians and cryptographers analyzing Argon2 for a good long while, before it becomes an every day recommendation. In the meantime, bcrypt is a sound choice.

@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