Overconfident developers that choose to write their own cryptography code have plagued the information security industry since before it was even an industry.
This in and of itself isn’t inherently a bad thing, despite the infosec truisms about never doing exactly that. Writing crypto code (but not deploying or publishing it!) is an important first step to understanding the algorithms.
One trend I’ve noticed (as I recently noted about Session) is developers incorrectly insisting that they aren’t rolling their own crypto because they use a lower-level cryptography library.
“If you want a picture of the future, imagine developers rolling their own crypto–forever.”
–if George Orwell was an applied cryptography expert
This misdeed isn’t limited to dubious apps that fork end-to-end encrypted messengers to strip off forward secrecy.
Feast your eyes on, How we share secrets at a fully-remote startup–a January 2025 reprint of an earlier 2024 blog post about the same cryptography code that originally fell victim to Bleichenbacher’s 1998 Padding Oracle Attack (which is possibly the oldest pitfall in real-world cryptography).
And, let me be very clear on this, the reason I want you to feast your eyes on this is NOT put this person on blast. They are by far not the first person to roll their own cryptography. They aren’t even the first one I’ve seen this week.
But they were kind enough to walk through their code and share their thoughts about what they wrote, and I think that sheds a lot of insight into how people think about cryptographic code.
The blog post in question starts off with a bit humility and the common refrain from security experts:
Don’t roll your own security
Like many hard areas of human knowledge, security/cryptography is one where the more you know, the more you realize you don’t know.
How we share secrets at a fully-remote startup
But if you scroll down a bit further, past the code and explanation, you’ll see this too:
Did we roll our own security?
No, not really. Our solution uses and trusts a lot of cryptography code from good sources: Node.js, its crypto module, and the OpenSSL library it’s based on. These are respected, well-maintained, commonly-used open-source tools, which get plenty of attention from security researchers.
How we share secrets at a fully-remote startup
Hey, this argument has a very familiar structure, doesn’t it?
The code in question is just about what you’d expect from a blog post with this sort of cognitive dissonance:
Oh, and did I mention that other folks tried to talk the author down from rolling their own implementation the first time around (i.e., six months ago)?
As tempting as it may be to dunk on this code or the accompanying blog post, at least they’re being open and transparent.
Care to wager how many people make similar design mistakes and ship them to production every week, without any oversight from the security community?
This is the part of the blog post where I could tell any of a dozen stories that would fit very elegantly as a complementary example to that blog post from a startup co-CEO.
Unfortunately, all of my best work is done under NDA.
So, I can’t actually give you any specifics, even if I wanted to. The conversations I’ve experienced over the years would give most infosec neophytes chills. The only silver lining is that I, and my peers, were successful in convincing the developers in question to correct their course.
Here are a few highlights to chew on:
md5($password)
as their key derivation function for libsodium.When it comes to artisanal cryptography, even large tech companies aren’t impervious to the trappings of ego.
My theory for why this phenomenon keeps happening is simple:
Most people do not fundamentally understand what rolling your own crypto actually means.
Their disagreement comes in layers.
Most critically, “rolling your own crypto” means spending any innovation tokens at any level of abstraction on cryptography without adequate assurance of correctness and/or peer review from cryptography experts (preferably ones with at least some experience breaking other implementations).
The admonishment isn’t limited to the Crystalline guy!
Just because you outsource your block cipher implementations to your programming language’s crypto
module doesn’t mean you’re not rolling your own crypto.
Cryptography doesn’t just exist at the primitive layer. Any protocols that use cryptography are, in fact, crypto! This is both radioactive and hazmat.
The other big miss from this oft-repeated phrase is: what exactly your own crypto?
Does working with a team obviate the “ownness” of this act?
Is the problem as simple as novelty? Surely not.
If it were as simple as that, adhering to standards would be safe. So why do so many JSON Web Tokens implementations make terrible mistakes?
In my humble opinion, there are multiple layers of this onion: The deeper you slice, the more you will cry.
When you hear an infosec person say, “Don’t roll your own crypto,” it isn’t immediately clear where they draw the line.
Fundamentally, I believe the core problem here is a lack of available and trustworthy cryptography tools for developers to use.
Whatever opinion you have about OpenSSL, you have to acknowledge it’s a “everything but the kitchen sink”, low-level cryptography library.
“I use OpenSSL” is not sufficient to implement, say, Messaging Layer Security (RFC 9420) and also declare you didn’t roll your own crypto.
Tink and libsodium are closer to the ideal, but fall short of being complete, off-the-shelf implementations of high-level protocols for developers to plug into their applications.
Even when cryptography nerds take action, historically, they’ve focused on the easy problems (wrapping standard AEADs with asymmetric cryptography), rather than addressing the harder problems.
Namely: Key management.
This is why I focused on key management first for my Fediverse E2EE project. I’m not even thinking about the actual end-to-end encryption logic again until the key management story is sorted.
Looking at the available tooling to developers offered by their programming languages and package manager ecosystems of open source software, everyone else seems to kick that fucking can down the road–hoping it will be someone else’s problem.
While I work to deliver a solid, reliable solution to the key management problem for my own end-to-end encryption design, overconfident developers the world over are rolling their own encryption–often while insisting they aren’t doing that.
To err is to be human, but to routinely make preventable mistakes because people with my exact skillset haven’t yet delivered easy-to-use, hard-to-misuse tooling in the programming languages actual developers use–meeting them where they are, as it were?
That’s frustration on a level that would make
eldritch horrors quiver in rage.
If those who study history are doomed to stand by helplessly while everyone else repeats it, that’s my curse as a cryptography nerd.
Header art: CMYKat and Harubaki, plus my poor Photoshop skills.