Experts in this field typically advise that you should never roll your own crypto algorithm. I’ve been guilty of saying as much myself. There’s only one problem with this sentiment.
It’s wrong.
Everyone who works in software that leverages cryptography should roll their own algorithms. Let’s look into three reasons why.
Demystifying the magic
Public key cryptography was one of the hardest topics for me to learn. Early in my career, there were a lot of folks talking about it and trying to simplify it on their blogs or in books. Unfortunately, most of these materials went too far in trying to dumb things down.
As a result, I didn’t fully understand the relationship between these keys and treated them as more or less interchangeable objects. That two parties could communicate securely by only ever exchanging their public keys made no sense – how could their private keys be used to decrypt or validate anything?
Over time I figured it out, thanks to working with some amazingly patient senior engineers. But the memory of being mystified by cryptography remained.
Especially when I had a meeting with a senior architect at a very large consulting firm that specializes in identity protection and authentication software. He wanted me to validate a new authentication scheme they were going to market as an alternative to OAuth. The clincher: it swapped the nature of public and private keys, necessitating both parties had access to the private bytes in order the communicate.
He was just as mystified as I had been, and we spent several hours working through this misunderstanding via a whiteboard.
Learning where mistakes are made
A few people offered some very valid critiques on my last post that included a toy implementation of the Vigenere cipher. The most important one was that my implementation is relatively insecure:
Why on Earth would you pass plaintext punctuation characters through to the ciphertext?
Passing punctuation (and even spaces) from the plaintext to the ciphertext presents a would-be attacker with a very easy way to begin cryptoanalysis. In other words, this leaks information about the structure of the plaintext and renders the ciphertext far easier to potentially decrypt even without the key.
The Vigenere cipher itself, though, is already an extremely weak encryption scheme. My implementation was intended to show how the algorithm worked, not to build a secure or reliable encryption mechanism.
It’s through building things yourself that you begin to understand what kinds of mistakes are possible – like passing punctuation through an encryption algorithm unchanged. Once you know where the landmines lie in a system, you’re better equipped to avoid or disarm them.
No black boxes
I’ve worked with some stellar engineers. One of the best I’ve worked with, though, didn’t understand cryptography at all. He knew what it was, he could generally describe the value it provided, but he had no idea how things worked under the hood.
To him, encryption algorithms were magical black boxes he used to sprinkle security into his program. And he used them exactly like that.
Which caused a problem.
During a third-party audit of our latest product, the auditors discovered a problem. He was doing almost everything correctly in code except for one critical thing. He initialized a string to hold a nonce passed into AES-GCM, but never populated it with anything.
His code was passing a static nonce of all zeros every time it encrypted anything.
Considering the fact that our code was used to protect personal health information, a reused nonce was a critical security failure. My teammate could see what he’d done wrong once the mistake was pointed out, but he didn’t understand why the error was so problematic. Thankfully, our auditor caught the problem and another engineer was able to fix the issue before any production data made it into the system.
Treating encryption algorithms like an opaque, impossible to understand black box is a fatal error in software engineering.
In short …
You absolutely should roll your own crypto algorithms in order to learn and understand what they’re doing under the hood. However, you should never use home-grown crypto in a production system.
Unless, of course, you are a professional cryptographer and have the proper proofs and research to back up the security of your algorithm and implementation.
Treating cryptography as something so advanced you’ll never understand it is negligent. You don’t need to obtain an advanced math degree and write formal proofs about the correctness or security of an algorithm. You don’t need to write a custom implementation that will pass a FIPS audit.
You do need to understand, at least from a high level, what the modules in your code are doing. The best way to gain this understanding is by doing it yourself, at least as a toy implementation.