Thomas Ptacek tweeted yesterday that "If you're not learning
crypto by coding attacks, you might not actually be learning crypto."
Judging by the number of twitter "favourites" and "retweets" of this comment, it
seems to have struck a chord; but with all respect to Thomas, I absolutely
disagree. Not only is it possible to learn cryptography without writing a line
of code, but coding attacks is entirely useless for learning about modern
cryptography; the best route to learning modern cryptography is a study of
mathematical proofs.
If we were still in the 1990s, I would agree with Thomas. 1990s cryptography
was full of holes, and the best you could hope for was to know how your tools
were broken so you could try to work around their deficiencies. This was a time
when DES and RC4 were widely used, despite having well-known flaws. This was a
time when people avoided using CTR mode to convert block ciphers into stream
ciphers, due to concern that a weak block cipher could break if fed input blocks
which shared many (zero) bytes in common. This was a time when people cared
about the "error propagation" properties of block ciphers — that is, how much of
the output would be mangled if a small number of bits in the ciphertext are
flipped. This was a time when people routinely advised compressing data before
encrypting it, because that "compacted" the entropy in the message, and thus
made it "more difficult for an attacker to identify when he found the right
key". It should come as no surprise that SSL, designed during this era, has had
a long list of design flaws.
Cryptography in the 2010s is different. Now we start with basic components
which are believed to be highly secure — e.g., block ciphers which are believed
to be indistinguishable from random permutations — and which have been
mathematically proven to be secure against certain types of attacks — e.g., AES
is known to be immune to differential cryptanalysis. From those components, we
then build higher-order systems using mechanisms which have been proven to not
introduce vulnerabilities. For example, if you generate an ordered sequence of
packets by encrypting data using an indistinguishable-from-random-permutation
block cipher (e.g., AES) in CTR mode using a packet sequence number as the CTR
nonce, and then append a weakly-unforgeable MAC (e.g., HMAC-SHA256) of the
encrypted data and the packet sequence number, the packets both preserve privacy
and do not permit any undetected tampering (including replays and reordering of
packets). Life will become even better once Keccak (aka. SHA-3) becomes more
widely reviewed and trusted, as its "sponge" construction can be used to
construct — with provable security — a very wide range of important
cryptographic components.
Cryptography in the 1990s was like trying to build a bridge: You spend a lot
of time worrying about making sure that your bridge will still stand even if
some of the welds aren't done perfectly, some of the bolts rust, periodic
loading results in metal fatigue, et cetera. Theory may say that a particular
design will work, but you know that practice never quite matches the theory, so
you build in margins of safety, making your structure more costly and more
complex as a result. Pure engineering.
Modern cryptography is different; rather than building a bridge, it is like
planning a gravity-assisted interplanetary trajectory. Sure, it's complex and
you have to get all the details right — but once you start moving, the only way
you will fail to reach your destination is if the laws of physics (or
mathematics) change. Modern cryptography has developed sufficiently that the
theory does match the practice — so rather than learning by watching
bridges fall down, it's sufficient to learn the theory, and follow one simple
rule: Only do what mathematics says you can do. Pure science.
I'm sure that for what Thomas does, having experience implementing attacks
against cryptographic code is very useful. After all, he makes is living finding
flaws in application security — and most of the cryptography he encounters is
likely to be 1990s-style cryptography. But that is an era which is best left in
the past; so for developers, I recommend a more modern approach to
cryptography — which means studying the theory and designing systems which you
can prove are secure.