April 2014
Open Source Quality Challenge Redux (9 April 2014)
Heartbleed: Don't Panic (11 April 2014)
Doing Crypto (22 April 2014)
What Does "Network Neutrality" Mean? (29 April 2014)

Doing Crypto

22 April 2014

The recent discovery of the goto fail and heartbleed bugs has prompted some public discussion on a very important topic: what advice should cryptologists give to implementors who need to use crypto? What should they do? There are three parts to the answer: don’t invent things; use ordinary care; and take special care around crypto code.

Don’t invent things
This oldest piece of advice on the subject is still sound; everyone who teaches or writes on the subject will repeat it. Never invent your own primitives or protocols. Cryptographic protocols are fiendishly difficult to get right; even pros often get them wrong. Encryption algorithms are even harder to design. It’s certainly true that there have been very few known attacks on bad crypto by hackers not working for a major government. But "few" is not the same as "none"—think of WEP—and many commercial sites have been targeted by governments. Besides, many crypto attacks are silent; the victims may never know what happened.

Custom crypto: just say no.

Use ordinary care
Crypto code is code, and is therefore susceptible to all the natural shocks that code is heir to. All the usual advice—watch out for buffer overflows, avoid integer overflows, and so on—applies here; crypto code is almost by definition security-sensitive. There’s no shortage of advice and tools; most of this is even correct.

Special care
Crypto code, though, is special; there are precautions that need to be taken that are irrelevant anywhere else. Consider things like timing attacks: if you’re using RSA but haven’t implemented it with all due paranoia, an attacker can recover your private key just by seeing how long it takes you to respond to certain messages. There are cache timing attacks: if the attacker can run programs on the same computer as your crypto code (and this isn’t a preposterous notion in a world of cloud computing), it’s possible to figure out an AES key by watching what cache lines are busy during an encryption or decryption operation. Alternatively, consider how hard it is to implement obvious advice like zeroing out keys after they’re used: if you write code to assign zeros to a variable you’ll never use again, a modern compiler can optimize that code out of existence. The problems are subtle and there aren’t widely-known sources of advice.

Nine years ago, Dan Boneh commented to me that "It’s amazing how tricky it is to implement Crypto correctly these days. I constantly tell my undergrad students that they should not try to implement existing systems themselves." It’s even more true today.

Some of these issues can be dealt with by sticking with a well-implemented, standards-adhering crypto library. Yes, there have been problems of late with several different such libraries—but most programmers will make at least as many mistakes on their own. Are we putting all of our eggs in one basket and exacerbating the monoculture problem? In this case, I prefer to fall back on Pudd’nhead Wilson’s advice here:

Behold, the fool saith, "Put not all thine eggs in the one basket"—which is but a manner of saying, "Scatter your money and your attention"; but the wise man saith, "Put all your eggs in the one basket and—WATCH THAT BASKET!"
Crypto is hard.