Philosophies of Cryptographic Libraries
I’ve maintained a popular cryptography library for years and in that time I’ve realized that many of the differences between cryptographic libraries flow from their creators' philosophies. Users of those libraries also have philosophies, which shape their expectations. These philosophies are often both in tension with one another, but also often implicit, leading to frustrating conversations. The goal of this post is to flesh out common philosophies, and how they come to be in tension with one another.
One of the major decisions a cryptographic library faces is which algorithms and crypto-systems to include. This seemingly straightforward choice reveals a lot about a library’s underlying philosophy. When thinking about whether an algorithm should be included, we tend to ask questions like, “is it broken?” In 2024 we might go further and distinguish between algorithms that are misuse-resistant (meaning that they avoid catastrophic failures even in situations where they aren’t used as intended) and those that aren’t. Is it the library’s responsibility to attempt to guarantee a secure outcome (“protect users from themselves”) by not providing insecure constructions, or should libraries provide “power tools” that can produce bad outcomes?
Where libraries fall on this spectrum is shaped by both their maintainers philosophies, as well as their users'.
Four Types of Cryptographic Users
In my experience, there’s often a significant gap between the backgrounds and priorities of crypto library developers and their users. Unsurprisingly, library creators tend to be deeply versed in cryptography, with strong opinions on best practices and security tradeoffs. We like to imagine that our users are like us, using our libraries as building blocks to implement cryptographic protocols, with a premium on security. While these users are real, they’re far from the only type of users a cryptographic library has.
First is the modal user of a cryptography library. They seem to have fairly standard needs, which are met by the availability of general purpose cryptographic algorithms (RSA, AES, HMAC, etc.). I say “seems to”, because we don’t hear much from this category of user. Their needs, therefore, are inferred from the absence of feedback, in contrast with our other user personas.
Second is the user that cryptographic library authors like best: other security engineers. Their interest is in misuse-resistance, and generally having the library be something that other engineers at their company, who aren’t part of the security team, can use without the security team needing to be too involved in micro-managing them.
The third, sharply contrasting and also more prevalent, type of user is one for whom security is not a priority at all. This may sound baffling, why use a cryptography library if you don’t care about security? For these users, cryptography is like JSON or base64, it’s a way to encode or decode data to be sent/received from a peer. Someone else has mandated that data must be AES encrypted or HMAC authenticated, and so they need to get close enough to that to communicate with their peer’s system. To security-oriented engineers, this can be a puzzling persona, but it’s nonetheless quite common.
The final type, who also frustrate cryptographic library authors, are security engineers. In contrast to our first group of security engineers, however, this group is interested in building tools, such as scanners, that deliberately interact with insecure cryptography. Therefore, they want libraries to implement insecure functions! These are some of the most vocal advocates for libraries including insecure functionality, because they value their ability to write scanners for insecure protocols above a library’s ability to prevent the development and usage of insecure protocols.
Because most ecosystems have at most a small number of cryptographic libraries (sometimes as few as one), combined with the imperative that non-experts should not develop their own cryptographic libraries, there’s generally a strong presumption that a given library must support all of these use cases, even though they’re plainly in tension (if not mutually exclusive) with one another.
Don’t roll your own crypto
The advice “don’t roll your own crypto” has been a staple of security wisdom for as long as I’ve been a professional engineer. But its meaning has shifted significantly over time. In its original form, it cautioned against designing custom cryptographic primitives, like block ciphers or hash functions. Today, virtually no one is attempting to create their own AES competitor, but the phrase remains omnipresent.
In 2024, this phrase is often used to mean “don’t design any element of a cryptographic system.” This expansive interpretation discourages developers from creating everything from custom TLS implementations to bespoke encrypted backup solutions. This can be quite perplexing, as the type of vulnerabilities you’re likely to introduce by designing your own block cipher are fairly different than the type you’ll introduce by designing your own encrypted cookie session storage.
While well-intentioned, this blanket advice creates a conundrum. Many developers face scenarios where off-the-shelf solutions don’t quite fit their needs (in no small part because there are relatively few composable off the shelf cryptographic systems). Engineers require the flexibility to implement cryptographic systems that aren’t entirely pre-packaged. Our challenge as library designers is to enable this flexibility while still steering users towards secure practices and pre-built solutions when appropriate.
Philosophies
Through my work, I’ve observed three primary philosophies that motivate cryptographic library designs:
One Right Answer: The first philosophy is that for any given use case (symmetric encryption, key exchange, asymmetric signatures, etc.) a library should provide exactly one option, which reflects a best practice. These types of libraries can do extremely well at enabling secure outcomes where they work, but tend to not be very useful for interoperating with external systems. As a result, users of libraries from this family frequently also use libraries from other philosophies. This philosophy finds significant purchase within internal libraries for organizations where security teams want to provide a right answer to its users.
All Secure Algorithms: A competing philosophy is that a library should simply include any algorithms that are secure, even if that means there are multiple choices for users to choose from. This is generally required to enable interoperability with existing use cases, and thus is a dominant philosophy of general purpose commercial and open source cryptography libraries.
Whatever Users Want: This goes further and provides things users might want, even if it’s not secure. Most mainstream libraries continue to offer MD5, suggesting that this is the real dominant philosophy.
In some sense all of these libraries have a place in the world. In another sense, the more use cases (including the need to be interoperable) that can be served from “One Right Answer” libraries, the more secure outcomes we’re likely to get.
It’s worth noting that the choice between these philosophies animates not just libraries, but also policies on what algorithms an entity is allowed to use.
The Path Forward
As library maintainers, we need to navigate these sometimes conflicting needs, while striving to enable and encourage secure results for our users. I believe concrete steps that maintainers can take to improve on the status quo are:
- Be explicit about our design philosophies, and what tradeoffs we’re making.
- Encourage the developments of standards that can become interoperable “One Right Answer” choices.
- Be willing to tell users that some use cases are beyond our scope.