Crypto 101: Learning What Each Primitive Supplies by Watching Weaker Constructions Fail

Crypto 101: Learning What Each Primitive Supplies by Watching Weaker Constructions Fail

Crypto 101 is Laurens Van Houtven's introduction to cryptography for programmers of any skill level. It grew out of a talk he gave at PyCon 2013. The book starts with the simplest primitives and adds new ones by showing why each becomes necessary. Its stated aim is to assemble them into complete cryptosystems such as TLS, GPG and OTR. Van Houtven frames the goal as programmer understanding: readers should see how complete cryptosystems work from a bird's-eye view and learn how to apply them in real software. Its exercises serve that goal by breaking inferior systems, so the reader learns exactly how each one fails.

The copy examined here calls itself an early pre-release, built from git commit 64e8ccf (0.6.0-95-g64e8ccf). Its copyright line spans 2013 to 2017, and its release year remains unverified. What makes it worth reading is the set of chapters built around attacks. In each of them the reader watches a weaker construction fail and can then name the requirement that the missing component supplies. That knowledge lets a programmer judge what a library call provides. For current deployment settings, the TLS chapter refers readers to continuously updated sources, because good configuration advice changes faster than a book can.

The one-time pad chapter sets the pattern. When two plaintexts are encrypted under the same pad, XORing the two ciphertexts makes the key appear twice and cancel. What remains is the XOR of the two plaintexts. In crib-dragging, an attacker slides likely fragments such as " the " or Content-Length across that result, and each correct guess reveals the key bytes at that position for every message that shares the pad. The argument's scope is exact: it covers a pad applied to more than one message, where identical key bytes cancel under XOR.

CBC bit-flipping carries the same XOR reasoning from reading messages to rewriting them. Flipping bits in one ciphertext block garbles that block's plaintext but flips exactly the same bits in the next plaintext block. In the book's cookie model, the attacker registers a user name padded with filler bytes, so that stretch of plaintext is known. XORing the filler with ;admin=1; makes the target string appear after decryption, and the attacker achieves it through bit flips alone. Van Houtven concludes that encryption is not authentication, and he points to authenticating the message as the repair, which the book develops later. This demonstration applies to unauthenticated CBC; authenticated modes lie outside its scope. Read together, the two chapters separate confidentiality from integrity: the pad attack reads messages, and the bit-flipping attack changes what they say.

Password storage adds a third requirement, the cost of each guess. Fast hash functions, used the same way everywhere, let attackers precompute tables that map common passwords to their hashes. Per-user salts defeat that precomputation, because every salt would need its own table. Van Houtven notes that salts convinced many programmers their job was done. A salt still leaves each individual guess cheap, so an attacker who holds the database can work through likely passwords on fast hardware. Protecting low-entropy passwords requires a key derivation function that is deliberately expensive to compute. The key derivation chapter separates that case from high-entropy secrets, for which the book presents HKDF. It explains that HKDF concentrates entropy but cannot make a weak password costly to guess.

Gaps in the prerelease are plainest here. Its password strength section is a TODO, the PBKDF2, bcrypt and scrypt headings stand empty, and a TODO line remains where GPU performance numbers were meant to go. The book establishes why a work factor is needed and leaves the choice of algorithm and parameters open; this review leaves them open as well.

The messaging chapters turn from what an attacker can read or alter to what evidence a conversation leaves behind. OpenPGP intentionally guarantees non-repudiation, which suits signed software releases or business invoices. OTR's designers wanted something different for one-on-one chat. Peers authenticate each other during the conversation, yet the protocol is designed so participants can later deny to third parties what they said. It is also designed for perfect forward secrecy, so that compromising a long-term key leaves earlier conversations protected. Comparing the two helps a programmer decide what proof an application's messages should produce. These properties are design goals, and they cannot stop a recipient from disclosing a conversation or capturing a screen. Coverage also stops short: Section 17.3, on OTR data exchange, consists of a TODO, and the appendices follow directly, so the book ends before a whole-book conclusion.

The book suits a programmer who already uses cryptography through a maintained library and wants to understand the requirement behind each call. Read the XOR, CBC, password storage and key derivation discussions closely. Then check your own code against what they establish. Confirm that your encryption interface authenticates ciphertext. Take your password store's expensive function and its parameters from current specifications and the library's own documentation. Check that your messaging protocol produces the kind of evidence your users expect. Where Crypto 101 leaves a TODO, go to those current sources for the answer.