Crypto design patterns
These days, when we do architecture and code reviews for clients we rarely see developers rolling their own crypto primitives. That’s a good thing! These days, we tend to see mistakes, or anti-patterns, at the next-highest level of abstraction.
Many years ago, when I was just starting out in software development, the Gang of Four published their book “Design Patterns”. This classic book arose out of a realization that:
- Developers would learn the fundamentals of object-oriented design in college.
- After graduating, developers continued to deepen their expertise in programming languages and frameworks (remember MFC, anyone?).
- Nobody was learning about higher-level design patterns (and importantly, anti-patterns).
- Each development shop would independently reinvent the wheel when it came to higher level concepts, and everyone would make the same mistakes.
I feel like this is where we are with crypto today. Developers aren’t writing their own crypto primitives (any more than they’d write their own hash table implementations), but we’re seeing the same mistakes over and over again in the practical application of crypto to common design problems.
Common crypto anti-patterns
Today, too few developers understand the most common design patterns for using crypto in the real-world. As a result, we still see countless anti-patterns when we do code reviews. The most common anti-patterns we see are:
- Mis-use of hashing
- Poor password hashing
- Not knowing that HMAC is a thing
- Not validating SSL/TLS certificates
- Not using separate data encryption keys (DEKs) when you should
- Not using built-in keystore managers in your stack of choice
- Private key material sprayed carelessly throughout the system (no trust boundaries)
- Supplying insufficient entropy or poor-quality randomness to crypto functions
The area where we tend to see these anti-patterns the most? Password-reset workflows, “remember me” tokens in cookies, unsubscribe links in custom mass emailers, and pretty much any time someone’s passing a hash in a URL parameter.
If you find yourself getting clever in your use of crypto primitives to solve a problem, chances are that experts have already solved your problem with a peer-reviewed crypto pattern.
I was happy to see that Google has released Tink, a small, useful Java crypto library that supports useful crypto patterns including AEAD and envelope encryption. Tink’s envelope encryption supports the most common cloud-based keystore management systems: Amazon KMS, Google Cloud KMS and also supports the Apple iOS keychain and Android keystore system.
What’s also lovely about Tink is that the authors have tried to make the API’s robust with respect to misuse or abuse. In other words, they’ve made it hard to screw up and they’ve followed the Principle of Least Astonishment.
What are you seeing out there?
I’d love to hear from those of you who code or review code professionally. Please comment below!
- What crypto anti-patterns do you see the most?
- Which parts of applications tend to have the same problems?
- What are other similar libraries to Tink?
- Which colleges do a good job teaching this stuff?