Section 10: Practice & Challenges
You have read nine sections of theory. Now comes the part that actually turns theory into skill: breaking things and building things. Cryptography is unusual among technical disciplines in that the fastest way to understand why a construction is designed the way it is, is to attack a version of it that lacks one of its defenses. Break a Caesar cipher and you understand why key space matters. Break a repeating-key Vigenère and you understand why key reuse is fatal — the same insight behind the two-time pad, keystream reuse in stream ciphers, and nonce reuse in AES-GCM. Factor a toy RSA modulus and you feel, in your fingers, why key size is the whole ballgame.
The complementary exercise is implementation. Writing AES or SHA-256 from the specification forces you to confront every detail the textbook glossed over: byte ordering, padding, the exact wiring of the round functions. You will emerge with a visceral understanding that no amount of reading provides — and a healthy respect for why we tell people never to ship their own crypto.
The five challenges below are ordered from easiest to hardest. Each has an answer box and a Check button. Your answer is hashed with SHA-256 locally in your browser and compared against a stored digest — nothing is ever sent anywhere, and the answers are not visible in the page source (view it and see!). Input is trimmed and lowercased before checking, so don't worry about capitalization or stray spaces. Hint buttons are there when you're stuck; using them costs you nothing but pride. Your progress is saved in your browser's localStorage.
Break This Cipher — five challenges
Everything you need to solve these was covered in Sections 2–6, and the interactive tools on those pages (Caesar shifter, Vigenère widget, frequency analyzer, modular arithmetic calculator) are legitimate weapons. Real cryptanalysts use tools; so should you.
Professional cryptanalysts stare at problems for days. If a challenge resists you, walk away, re-read the relevant section, and come back. The "aha" when a wall of gibberish resolves into English is worth earning honestly — but there is also zero shame in using hints. The goal is understanding, not machismo.
Code implementation exercises
Breaking toy ciphers teaches you attacks; implementing real primitives teaches you the constructions. The projects below are ordered by difficulty and each links to official test vectors so you can prove your implementation is correct rather than merely plausible. Pick any language you're comfortable in — Python is the community default, but the exercises are language-agnostic.
Never, ever use your own implementations in production. Hand-rolled crypto is almost always vulnerable to timing attacks, cache attacks, and subtle spec violations that test vectors don't catch. These exercises exist so you understand what libraries like libsodium and the platform crypto APIs do for you — and why you should let them.
Goal: a program that takes arbitrary Caesar ciphertext and outputs the plaintext with no key provided.
Steps: (1) implement encrypt/decrypt for a given shift; (2) compute letter frequencies of the ciphertext; (3) score all 26 shifts against standard English frequencies using chi-squared distance; (4) output the best-scoring candidate.
Verify: feed it Challenge 1 above; encrypt random Wikipedia paragraphs with random shifts and confirm 100% recovery on texts over ~50 letters.
What you learn: statistical attacks, why "security by small key space" is no security, and the scoring machinery you'll reuse for XOR and Vigenère breaking in Cryptopals.
Goal: a byte-for-byte correct SHA-256 built only from the FIPS 180-4 specification.
Steps: (1) implement padding (append 0x80, zeros, 64-bit length); (2) build the 64-word message schedule with the σ0/σ1 functions; (3) implement the compression function — 64 rounds of Ch, Maj, Σ0, Σ1 over eight working variables; (4) chain the state across blocks and serialize the digest big-endian.
Verify: the FIPS 180-4 examples — "abc" must give ba7816bf… — plus the NIST CAVP short/long message vectors. Also compare against CL.sha("SHA-256", text) right here in this site.
What you learn: Merkle–Damgård construction, why length extension exists, bit-fiddling discipline, and how a "random-looking" function is actually completely deterministic wiring.
Goal: encrypt and decrypt single 16-byte blocks with AES-128, matching official vectors exactly.
Steps: (1) represent the state as the 4×4 byte grid (column-major — this trips everyone up); (2) implement SubBytes with the S-box table, ShiftRows, MixColumns (multiplication in GF(28) — implement xtime first), and AddRoundKey; (3) implement the key schedule with RotWord/SubWord/Rcon; (4) wire 10 rounds together, remembering the final round skips MixColumns; (5) implement the inverse operations for decryption; (6) optionally add ECB and CBC modes on top and PKCS#7 padding.
Verify: FIPS-197 Appendix B walks a single block through every intermediate round state — check yourself round by round, not just at the end. Appendix C gives full key-expansion vectors.
What you learn: substitution–permutation networks, finite-field arithmetic in practice, why ECB leaks patterns, and (if you time your S-box lookups) an intuition for cache-timing side channels.
Goal: full RSA keygen, encrypt, and decrypt with real-sized (2048-bit) keys.
Steps: (1) implement Miller–Rabin primality testing on big integers; (2) generate random candidate primes until two pass; (3) compute n, φ(n) (or better, λ(n)), and d via extended Euclid; (4) implement modular exponentiation by square-and-multiply (do not compute me first!); (5) round-trip messages; (6) then read the OAEP spec (RFC 8017) and understand why raw "textbook RSA" — which you just built — is malleable, deterministic, and broken for real use.
Verify: round-trip property (decrypt(encrypt(m)) = m); sign/verify with your own keys; cross-check small examples against Section 6's widget; validate primes against a library's isprime.
What you learn: why RSA is slow, where the security really lives (factoring), the enormous gap between a textbook primitive and a deployable scheme, and respect for padding.
Goal: a working Signal-style Double Ratchet between two simulated parties, using a library (yes, a library!) for the X25519, HKDF, and AEAD primitives — the exercise is the protocol, not the primitives.
Steps: (1) implement the symmetric-key ratchet: a KDF chain producing per-message keys; (2) implement the Diffie–Hellman ratchet: new X25519 keypair per sending turn, mixed into the root key; (3) handle out-of-order messages with skipped-message-key storage; (4) add header encryption if you're feeling brave; (5) simulate a conversation where one party's state is compromised mid-stream and verify that past messages stay secret (forward secrecy) and future ones recover (post-compromise security).
Verify: against the published Signal Double Ratchet specification (signal.org/docs); interop-test two independent implementations of your own; property-test the compromise scenarios.
What you learn: how modern secure messaging actually works, key-derivation hygiene, state-machine design, and why protocol security is a different discipline from primitive security.
External practice platforms
This site ends here, but the road doesn't. These platforms have thousands of hours of curated crypto practice, and every serious practitioner has ground through at least one of them.
CryptoHack
Gamified crypto challenges solved in Python, from "encode this" to elliptic-curve exploitation. Gentle on-ramp, brutal endgame, superb community. The single best follow-on to this course — start with the Introduction and General categories.
02Cryptopals
The classic. Eight sets of implementation-and-attack challenges (byte XOR through ECB cut-and-paste, CBC padding oracles, RSA attacks). Language-agnostic, no hand-holding. Sets 1–2 are approachable now; set 8 will humble anyone.
03picoCTF
Carnegie Mellon's beginner-friendly CTF platform with a permanent practice gym. Its cryptography category is ideal if you want variety (plus forensics, web, pwn) and a competition format. Great first CTF experience.
04OverTheWire: Krypton
A short wargame focused purely on classical ciphers (Caesar through Vigenère and beyond), played over SSH. Easy difficulty, but teaches you the command-line workflow real CTF players use. An afternoon well spent after Section 3.
05Root Me — Cryptanalysis
A large French/English challenge site whose cryptanalysis section spans encodings, classical ciphers, hash cracking, and modern attacks. Medium difficulty overall; use it for breadth once CryptoHack starts feeling comfortable.
06MysteryTwister
An ongoing cipher contest with four difficulty levels, from pen-and-paper classical puzzles to unsolved research-grade problems (including real historical ciphertexts). Perfect when you want puzzles rather than programming.
A suggested learning path
- Finish this site — including all five challenges above, unhinted if you can manage it.
- CryptoHack: Introduction + General — cements encodings, XOR, and modular arithmetic with instant feedback.
- Cryptopals Sets 1–2 — build the XOR/frequency toolkit for real, then break ECB and CBC with your own hands.
- Implement SHA-256 (Project 2 above) — your first full primitive from a spec.
- Cryptopals Sets 3–4 — stream ciphers, CBC padding oracles, length extension, timing leaks.
- CryptoHack: RSA + Elliptic Curves — the number theory gets real; keep Section 2 and 6 open beside you.
- Dan Boneh's Cryptography I (Coursera) — now the proofs and security definitions will land, because you've met every object they formalize.
- Read Serious Cryptography cover to cover — it will read like a conversation with an old friend.
Budget six months at a few hours a week. That is genuinely all it takes to go from "read a website once" to "can hold my own in a CTF crypto category and reason about real designs".
Best overall resources
The strongest single recommendations from the whole course, in one place.
Closing words
Bruce Schneier's famous observation bears repeating one last time: "Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can't break." The corollary is the entire philosophy of this field — security comes not from cleverness in isolation but from surviving the sustained, public attention of people trying to destroy your work. You are now one of those people. You know enough to break weak systems, enough to appreciate strong ones, and — most importantly — enough to know how much you don't yet know. Keep the humility, keep the curiosity, and keep breaking things (that you're allowed to break). The rest is practice.