Cryptography Fundamentals: Real World Learning Projects
Goal: Build a working mental model of modern cryptography by implementing core primitives (hashes, block ciphers, public-key algorithms) and then composing them into protocols (key exchange, TLS, secure storage). You will learn what each primitive guarantees, what it cannot guarantee, and how real systems fail when the pieces are composed incorrectly. By the end, you can read a protocol description and reason about confidentiality, integrity, authenticity, and forward secrecy without hand-waving. You will also be able to validate your implementations against known test vectors and explain why constant-time and randomness discipline matter.
Why Cryptography Matters
Cryptography is the quiet infrastructure behind modern life: every HTTPS page load, software update, password login, payment, and private message depends on it. It is not about “unbreakable” math; it is about making attacks infeasible within a defined threat model.
Real-world momentum (2024-2025):
- Web encryption is now the default: Let’s Encrypt reports serving over 762 million websites in 2025, and notes that in many regions over 95% of page loads are encrypted. This is a historic shift from the web’s plaintext origins. (Source: Let’s Encrypt 2025 annual report letter)
- Human and credential weaknesses dominate breaches: The Verizon 2024 DBIR reports 68% of breaches involve a human element, and 31% of breaches over the past decade involve stolen credentials. This explains why strong authentication and safe password handling are core crypto applications. (Source: Verizon 2024 DBIR news release)
- Extortion and ransomware are mainstream: The same report notes 32% of breaches involve extortion, highlighting why encryption + backups + key management are operationally critical. (Source: Verizon 2024 DBIR news release)
The paradigm shift:
- Old security assumed trusted networks.
- Modern security assumes hostile networks and uses cryptography to enforce trust.
Old Model (Trust the Network) Modern Model (Trust the Math)
┌────────────────────────────┐ ┌──────────────────────────────┐
│ Internal network is safe │ │ Network is hostile │
│ Encrypt only "important" │ ---> │ Encrypt all traffic │
│ Perimeter decides access │ │ Identity + crypto decides │
└────────────────────────────┘ └──────────────────────────────┘
Prerequisites & Background Knowledge
Essential Prerequisites (Must Have)
Programming Skills:
- Comfortable writing C functions, structs, and pointer-based code
- Confident with bitwise operations (AND, OR, XOR, shifts, rotates)
- Ability to write CLI tools and parse arguments
Math Fundamentals:
- Modular arithmetic (mod, inverse, exponentiation)
- Basic probability / entropy intuition
- Comfort with binary representation of numbers
Security Fundamentals:
- Understand confidentiality, integrity, authentication
- Know what a threat model is and why it matters
Helpful But Not Required
- Big integer libraries (GMP, OpenSSL BIGNUM)
- Python for quick verification scripts
- Familiarity with network packet traces (Wireshark)
Self-Assessment Questions
- Can you explain the difference between encryption and hashing in one sentence each?
- Can you implement a 32-bit rotate-right function without looking it up?
- Can you reason about
a^b mod pand why it repeats with period p-1 (for prime p)? - Have you used
opensslto hash or encrypt files from the CLI? - Can you describe what a nonce is and why reuse is dangerous?
If you answered “no” to questions 1-3, spend a week on fundamentals before starting.
Development Environment Setup
Required Tools:
- Linux or macOS
- C compiler (gcc or clang)
- Python 3.10+
- OpenSSL CLI
Recommended Tools:
valgrindor sanitizers (-fsanitize=address,undefined)hexdump/xxdopensslheaders orlibsodium(for reference checks)
Testing Your Setup:
$ gcc --version
$ python3 --version
$ openssl version
$ printf "abc" | openssl dgst -sha256
Time Investment
- Simple projects (1, 6): Weekend (4-8 hours)
- Moderate projects (2, 3): 1-2 weeks each
- Complex projects (4, 5, 7): 2-3 weeks each
- Total sprint: ~2-3 months if done sequentially
Important Reality Check
Cryptography is unforgiving: a tiny bug can break the entire system. Expect to re-read specs, fail test vectors, and debug bit-level issues. That is normal.
How to Use This Guide
- Read the Core Concept Analysis once before coding.
- For each project, implement the minimum version first (even if slow).
- Validate against known test vectors before adding features.
- Keep a “crypto log”: note every bug and what it taught you.
- Only optimize after the logic is correct.
Big Picture / Mental Model
Entropy -> Key Derivation -> Symmetric Crypto -> Authentication -> Storage/Transport
| | | | |
v v v v v
RNG KDF/HKDF AES/ChaCha HMAC/AEAD TLS/Vault
The projects move left to right: from primitives to compositions.
Core Concept Analysis
Security Goals and Threat Models
Before you write a line of crypto code, you must know what you are defending against.
Goal Protects Typical primitive
-------------------------------------------------------------------
Confidentiality Secrets stay secret AES, ChaCha20
Integrity Data is unchanged Hash, HMAC, AEAD
Authenticity Sender is who they say Signatures, MAC
Forward Secrecy Past sessions stay safe Ephemeral DH
Cryptography does not promise “impossible to break.” It promises “infeasible given a threat model.” Your projects will explicitly define those models, then test how systems fail when the model is violated.
Symmetric Crypto: Confusion, Diffusion, Modes
Symmetric encryption is fast and protects bulk data. The two goals are confusion (hide relationships) and diffusion (spread influence).
Plaintext -> [Substitution] -> [Permutation] -> [Mix] -> Ciphertext
(confusion) (diffusion) (diffusion)
Block ciphers (AES) need modes to handle real data. ECB leaks structure, CBC hides it, GCM adds integrity. You will see this when you encrypt images.
Hash Functions and Integrity
Hash functions compress arbitrary data into a fixed-size digest. The goal is to make collisions and preimages infeasible.
Message -> [Padding] -> [Compression rounds] -> 256-bit digest
Hashes are not encryption. They are the basis for integrity checks, signatures, and password storage (when paired with slow KDFs).
Public-Key Cryptography: Trapdoors and Signatures
Public-key crypto lets strangers communicate securely. RSA is built on factoring; ECC uses discrete log hardness.
Public key (share) + Private key (keep) => Encryption / Signatures
You will implement RSA to understand key generation, modular arithmetic, and why padding (OAEP, PSS) is mandatory.
Key Derivation and Authenticated Encryption
Passwords are weak; cryptographic keys must be strong. KDFs (Argon2, PBKDF2, scrypt) slow attackers. AEAD modes (AES-GCM, ChaCha20-Poly1305) provide confidentiality + integrity in one step.
Password + Salt + Work Factor -> KDF -> Key
Key + Nonce + Data -> AEAD -> Ciphertext + Auth Tag
Key Exchange and Forward Secrecy
Diffie-Hellman lets two parties derive a shared secret without exposing it. Ephemeral keys give forward secrecy: even if a long-term key leaks, past sessions stay safe.
Alice: g^a mod p ---------> Bob
Bob: g^b mod p ---------> Alice
Shared secret: g^(ab) mod p (never sent)
Protocol Composition: Why TLS Is Hard
Real security lives in protocols, not primitives. TLS is a choreographed sequence that uses randomness, certificates, key exchange, and AEAD to prevent downgrade and MITM.
ClientHello -> ServerHello -> Key Exchange -> Handshake -> Encrypted App Data
Implementation Risks (The Practical Landmines)
- Side channels: branching on secret data leaks timing info
- Bad randomness: weak entropy ruins everything
- Nonce reuse: breaks AEAD security instantly
- Padding oracles: “minor” errors become full breaks
Concept Summary Table
| Concept Cluster | What You Need to Internalize |
|---|---|
| Symmetric encryption | Confusion/diffusion, block vs stream, why modes matter |
| Hashing & integrity | Hash properties, padding, collision resistance |
| MAC / AEAD | Integrity + confidentiality, nonce discipline |
| Public-key crypto | Trapdoor functions, keypairs, padding safety |
| Key derivation | Passwords are weak; KDFs trade time for safety |
| Key exchange | Shared secrets without sharing, forward secrecy |
| Protocol composition | Correct sequencing and state are everything |
| Implementation risk | Constant-time code, randomness, side channels |
Deep Dive Reading by Concept
Foundations & Threat Models
| Concept | Book & Chapter | Why This Matters |
|---|---|---|
| Threat models, CIA, risk | Foundations of Information Security by Andress - Ch. 1-2 | Establishes security goals and attacker models |
| Modern crypto overview | Serious Cryptography (2nd Ed.) by Aumasson - Ch. 1 | Maps the modern crypto landscape |
| Bit operations & integers | Computer Systems: A Programmer’s Perspective - Ch. 2 | Makes bitwise logic and integer representation concrete |
Symmetric and Hashing
| Concept | Book & Chapter | Why This Matters |
|---|---|---|
| Block ciphers, modes | Serious Cryptography (2nd Ed.) - Ch. 3 | How AES-style designs work |
| Hash functions | Serious Cryptography (2nd Ed.) - Ch. 4-5 | Avalanche effect, Merkle-Damgard |
| MAC / HMAC basics | Serious Cryptography (2nd Ed.) - Ch. 6 | Integrity and authentication |
Public-Key and Protocols
| Concept | Book & Chapter | Why This Matters |
|---|---|---|
| RSA fundamentals | Serious Cryptography (2nd Ed.) - Ch. 9 | Key generation, padding, signatures |
| Diffie-Hellman | Understanding Cryptography by Paar & Pelzl - Ch. 11 | Key exchange intuition |
| TLS 1.3 design | RFC 8446 (TLS 1.3) - Sections 4-7 | Protocol composition details |
Engineering and Pitfalls
| Concept | Book & Chapter | Why This Matters |
|---|---|---|
| Safe randomness | Serious Cryptography (2nd Ed.) - Ch. 2 | RNG requirements |
| Secure implementation | Effective C (2nd Ed.) by Seacord - Ch. 5-7 | Defensive coding in C |
Quick Start: Your First 48 Hours
Day 1 (4 hours):
- Read “Security Goals” and “Symmetric Crypto” above
- Implement Caesar cipher encrypt/decrypt
- Run a frequency analysis on sample ciphertext
Day 2 (4 hours):
- Implement Vigenere encryption/decryption
- Add Kasiski/Friedman key length guesser
- Use the “Real World Outcome” checklist for Project 1
By the end of the weekend, you will understand why classical ciphers fail and why modern primitives exist.
Recommended Learning Paths
Path 1: The Low-Level Builder (C-first)
- Project 1 (Classic Ciphers)
- Project 2 (SHA-256)
- Project 4 (AES)
- Project 3 (RSA)
- Project 5 (Password Manager)
Path 2: The Protocol Thinker
- Project 6 (Diffie-Hellman Visualizer)
- Project 7 (TLS 1.3 Simulator)
- Project 2 (SHA-256)
- Project 4 (AES)
- Project 3 (RSA)
Path 3: The Completionist
Follow the recommended order at the bottom, including all projects.
Success Metrics
By the end, you should be able to:
- Implement SHA-256 and AES that match official test vectors
- Generate RSA keys and interoperate with OpenSSL
- Explain why AES-ECB leaks structure but AES-CBC does not
- Demonstrate forward secrecy with ephemeral DH
- Simulate a TLS 1.3 handshake and reason about transcript integrity
Crypto System Walkthrough (Example Flow)
User password -> KDF -> Symmetric key -> AEAD encrypt -> Vault file
| | |
v v v
Salt + work factor Nonce + tag Tamper detection
This is the end-to-end path you will build in Project 5.
Implementation Navigation Cheatsheet
Specs and test vectors:
- AES: NIST FIPS 197 (official AES spec)
- SHA-256: NIST FIPS 180-4 (SHS)
- TLS 1.3: RFC 8446 (TLS 1.3)
OpenSSL quick checks:
# SHA-256
$ printf "abc" | openssl dgst -sha256
# AES-128-ECB
$ openssl enc -aes-128-ecb -K <hexkey> -in input.bin -nopad -nosalt -out out.bin
# RSA key sanity
$ openssl rsa -in private.pem -check
Debugging Toolkit
xxd -g 1orhexdump -Cto inspect bytesgdb/lldbfor step-through in round functionsvalgrindor ASAN for memory errorsopenssl dgst,openssl enc,openssl pkeyutlas correctness oracles- Custom “trace” mode to log intermediate state per round
Cryptography Data Structure Atlas
Common structures you will likely build:
sha256_ctx:h[8](hash state)buffer[64](message block)total_len(bytes processed)
aes_state[4][4]:- 16-byte state matrix for SubBytes/ShiftRows/MixColumns
rsa_key:n, e, d, p, q, dp, dq, qinv(CRT parameters)
dh_params:p, g(prime + generator)
tls_transcript:hash_ctx(running transcript hash)handshake_state(state machine)
Crypto Code Review Checklist
- No branching or memory access on secret data (constant-time)
- Nonces are never reused (AEAD discipline)
- All randomness uses CSPRNG, not
rand() - Keys and sensitive buffers are zeroized after use
- All test vectors pass exactly
- All failure cases are explicit and safe
Glossary of Crypto Terms
- AEAD: Authenticated Encryption with Associated Data
- Nonce: A unique value used once per encryption
- Padding oracle: Leak caused by different error paths
- Forward secrecy: Past sessions safe after key compromise
- HMAC: Hash-based Message Authentication Code
- KDF: Key Derivation Function
Common Failure Signatures
“Bad MAC” or “Tag mismatch”
- Why: Wrong key, nonce reuse, or tampered ciphertext
- Fix: Re-check nonce generation and key derivation
“Invalid padding”
- Why: Decryption is wrong or padding scheme mismatched
- Fix: Validate mode and padding format
“Signature verify failed”
- Why: Mismatch of hash algorithm or padding
- Fix: Confirm PSS/OAEP parameters and hash choice
Cryptography Reading Plan (2 Weeks)
Week 1:
- Serious Cryptography Ch. 1-3
- CSAPP Ch. 2 (bitwise and integers)
Week 2:
- Serious Cryptography Ch. 4-6
- Understanding Cryptography Ch. 11 (Diffie-Hellman)
Project 1: Classic Cipher Toolkit
- Main Programming Language: C
- Alternative Programming Languages: Python, Rust
- Coolness Level: Level 2: Practical but Forgettable
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 1: Beginner
- Knowledge Area: Cryptography
- Software or Tool: Classic ciphers
- Main Book: “The Code Book” by Simon Singh
What you’ll build: A CLI tool that encrypts/decrypts Caesar, Vigenere, and substitution ciphers, plus a frequency-analysis cracker that attempts to recover plaintext.
Why it teaches cryptography: These ciphers fail in predictable ways. Building both the cipher and the breaker shows why modern crypto needs large key spaces and non-linear diffusion.
Core challenges you’ll face:
- Implementing encryption/decryption logic
- Building frequency analysis and scoring
- Cracking Vigenere with Kasiski or Friedman
- Handling punctuation/case safely
Real World Outcome
What you will see:
- A CLI that can encrypt/decrypt classic ciphers
- A cracking mode that outputs ranked plaintext guesses
- Frequency histograms for ciphertext analysis
Command Line Outcome Example:
$ ./cipher-cli encrypt --cipher caesar --shift 7 --text "attack at dawn"
Cipher: CAESAR (shift=7)
Ciphertext: haahjr ha khdu
$ ./cipher-cli crack --cipher auto --text "haahjr ha khdu"
Detected cipher: CAESAR
Top candidates:
[1] shift=7 score=0.92 "attack at dawn"
[2] shift=19 score=0.51 "haahjr ha khdu" (low confidence)
$ ./cipher-cli crack --cipher vigenere --text "lxfopv ef rnhr"
Guessed key length: 5
Top key guess: "lemon"
Plaintext: "attack at dawn"
The Core Question You’re Answering
“Why do simple substitution ciphers fail even when the attacker does not know the key?”
By building both cipher and cracker, you learn how statistical structure breaks naive secrecy.
Concepts You Must Understand First
- Substitution vs. Transposition
- Why is substitution vulnerable to frequency analysis?
- Book Reference: “Serious Cryptography” Ch. 1
- English letter frequency
- What makes ‘E’ and ‘T’ stand out?
- Book Reference: “The Code Book” Ch. 1-2
- Kasiski/Friedman tests
- How does repeated plaintext leak key length?
- Book Reference: “The Code Book” Ch. 2
Questions to Guide Your Design
- How will you normalize text (case, punctuation, spaces)?
- What scoring function will rank plaintext candidates?
- How will you avoid bias when comparing different key lengths?
Thinking Exercise
The Frequency Trap
Given ciphertext:
GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT
- Which letters are most frequent?
- What Caesar shift would map that frequency to ‘E’?
- Why does the same trick fail for one-time pads?
The Interview Questions They’ll Ask
- Why are classical ciphers insecure?
- How does frequency analysis work?
- Why does Vigenere resist single-letter frequency analysis?
- What is Kasiski examination?
- How would you score candidate plaintexts?
Hints in Layers
Hint 1: Caesar brute force is tiny
for (int shift = 0; shift < 26; shift++) {
decrypt_caesar(out, in, shift);
score_candidate(out);
}
Hint 2: Keep two alphabets Map plaintext alphabet to ciphertext alphabet for substitution.
Hint 3: Kasiski counts repeated trigrams Track distances between repeats and compute the GCD.
Hint 4: Verify quickly
$ ./cipher-cli crack --cipher caesar --text "..."
Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Classical ciphers | “The Code Book” by Simon Singh | Ch. 1-2 |
| Crypto foundations | “Serious Cryptography” by Aumasson | Ch. 1 |
Common Pitfalls & Debugging
Problem: “Cracker never finds the correct shift”
- Why: You scored punctuation or mixed case
- Fix: Normalize to lowercase A-Z only
- Quick test: Confirm histograms ignore spaces
Problem: “Vigenere key length always wrong”
- Why: Text too short or noisy
- Fix: Require minimum ciphertext length before guessing
Definition of Done
- Caesar, Vigenere, substitution encrypt/decrypt round-trip correctly
- Caesar crack works in <1 second for 1 KB input
- Vigenere key length guess within +/-1 on known samples
- Crack output shows top 3 candidate plaintexts
Project 2: SHA-256 From Scratch
- Main Programming Language: C
- Alternative Programming Languages: Rust, Go
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: Cryptography
- Software or Tool: Hash functions
- Main Book: “Serious Cryptography” by Jean-Philippe Aumasson
What you’ll build: A full SHA-256 implementation that matches standard test vectors.
Why it teaches cryptography: Hashing forces you to reason about padding, compression, and avalanche effects. Tiny changes produce wildly different outputs.
Core challenges you’ll face:
- Message padding to 512-bit blocks
- Compression function with 64 rounds
- Bitwise rotations and shifts
- Matching NIST test vectors exactly
Real World Outcome
What you will see:
- A CLI that hashes files or strings
- A test suite that verifies official vectors
- Avalanche tests that flip ~50% of output bits
Command Line Outcome Example:
$ ./sha256 "abc"
SHA256("abc") = ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
$ printf "abc" | openssl dgst -sha256
SHA2-256(stdin)= ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
$ ./sha256 --avalanche "hello" "jello"
Differing bits: 129 / 256 (50.39%)
The Core Question You’re Answering
“How do we turn arbitrary input into a fixed-length digest where tiny changes explode into randomness?”
This project shows how padding, message scheduling, and mixing create the avalanche effect.
Concepts You Must Understand First
- Bitwise rotation and shifts
- Why is rotate-right different from shift-right?
- Book Reference: “Computer Systems: A Programmer’s Perspective” Ch. 2
- Merkle-Damgard construction
- Why do we pad to full blocks?
- Book Reference: “Serious Cryptography” Ch. 4
- Test vectors
- Why must they match exactly?
- Book Reference: “Serious Cryptography” Ch. 4-5
Questions to Guide Your Design
- How will you represent 32-bit words and ensure correct overflow?
- How will you handle streaming input across multiple blocks?
- How will you verify intermediate state for debugging?
Thinking Exercise
One Bit Flip
Hash the string “hello” and then hash “jello”. Predict how many output bits should flip. Why is it not 100%?
The Interview Questions They’ll Ask
- Explain the avalanche effect.
- Why does SHA-256 pad with the message length?
- What is a collision and why does it matter?
- How does a compression function differ from encryption?
- Why are hash functions used in signatures?
Hints in Layers
Hint 1: Implement padding first
append_bit(1);
append_zeros_until_len_mod_512_is_448();
append_64bit_len();
Hint 2: Use helper macros
#define ROTR(x,n) ((x >> n) | (x << (32 - n)))
Hint 3: Print intermediate state Dump the 8-word state after each round for one test vector.
Hint 4: Compare with OpenSSL
$ printf "abc" | openssl dgst -sha256
Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Hash design | “Serious Cryptography” | Ch. 4-5 |
| Bitwise ops | “Computer Systems: A Programmer’s Perspective” | Ch. 2 |
Common Pitfalls & Debugging
Problem: “Digest differs from test vector”
- Why: Padding or endianness mismatch
- Fix: Verify message length encoding and byte order
- Quick test: Hash “abc” test vector
Problem: “Works on short inputs, fails on long”
- Why: Block chaining or length counter bug
- Fix: Track total bytes processed separately
Definition of Done
- Passes all official SHA-256 test vectors
- Streaming input works across multiple blocks
- Avalanche test shows ~50% bit flips
- CLI matches
openssl dgst -sha256
Project 3: RSA Implementation with Key Generation
- Main Programming Language: C
- Alternative Programming Languages: Rust, Go
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: Cryptography
- Software or Tool: RSA
- Main Book: “Serious Cryptography” by Jean-Philippe Aumasson
What you’ll build: RSA key generation, encryption/decryption, and signing/verification with OAEP/PSS padding.
Why it teaches cryptography: RSA makes number theory concrete. You will implement modular exponentiation, understand why padding matters, and see the costs of big integers.
Core challenges you’ll face:
- Large prime generation
- Modular exponentiation without overflow
- Modular inverse for private key
- Secure padding (OAEP/PSS)
Real World Outcome
What you will see:
- A keypair generator that outputs PEM keys
- Encryption/decryption that interoperates with OpenSSL
- Sign/verify that matches OpenSSL outputs
Command Line Outcome Example:
$ ./rsa-keygen --bits 2048 --out ./keys
Generated keys:
private.pem
public.pem
$ ./rsa-encrypt --pub ./keys/public.pem --in msg.txt --out msg.enc
$ ./rsa-decrypt --priv ./keys/private.pem --in msg.enc
Decrypted message: "hello world"
$ openssl rsautl -encrypt -pubin -inkey ./keys/public.pem -in msg.txt -out msg2.enc
$ ./rsa-decrypt --priv ./keys/private.pem --in msg2.enc
Decrypted message: "hello world"
The Core Question You’re Answering
“How can anyone encrypt to me, but only I can decrypt?”
RSA makes the trapdoor idea tangible and shows why padding is part of security, not optional.
Concepts You Must Understand First
- Modular arithmetic and Euler’s totient
- Why do we need phi(n)?
- Book Reference: “Math for Security” Ch. 4
- Modular exponentiation
- Why is square-and-multiply required?
- Book Reference: “Algorithms” by Sedgewick - Section 4.1
- Padding schemes (OAEP/PSS)
- Why is textbook RSA unsafe?
- Book Reference: “Serious Cryptography” Ch. 9
Questions to Guide Your Design
- Will you use a big integer library or implement your own?
- How will you generate cryptographic primes safely?
- How will you encode/decode OAEP and PSS?
Thinking Exercise
The Small RSA Trap
If p=61, q=53, e=17, can you compute d? What breaks if p and q are too small?
The Interview Questions They’ll Ask
- Why is RSA called a trapdoor function?
- Why must RSA use padding?
- How do you generate secure primes?
- What is CRT optimization and why is it risky?
- Why is RSA slower than symmetric crypto?
Hints in Layers
Hint 1: Use a big integer library Start with OpenSSL BIGNUM or GMP for correctness.
Hint 2: Modular exponentiation
while (exp > 0) {
if (exp & 1) result = (result * base) % mod;
base = (base * base) % mod;
exp >>= 1;
}
Hint 3: OAEP uses hash + MGF1 Implement MGF1 using your SHA-256 from Project 2.
Hint 4: Verify with OpenSSL
$ openssl rsautl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.enc
Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| RSA basics | “Serious Cryptography” | Ch. 9 |
| Modular arithmetic | “Math for Security” | Ch. 4 |
| Algorithms | “Algorithms” by Sedgewick | Section 4.1 |
Common Pitfalls & Debugging
Problem: “Key generation takes forever”
- Why: Prime test too slow
- Fix: Use Miller-Rabin with enough rounds
Problem: “OpenSSL won’t decrypt my ciphertext”
- Why: Padding mismatch
- Fix: Ensure OAEP parameters match
Definition of Done
- 2048-bit key generation completes in <1 minute
- Encrypt/decrypt round-trip works
- OAEP and PSS interoperate with OpenSSL
openssl rsa -checkvalidates your key
Project 4: AES-128 Block Cipher Implementation
- Main Programming Language: C
- Alternative Programming Languages: Rust, Go
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 3: Advanced
- Knowledge Area: Cryptography
- Software or Tool: AES
- Main Book: “Serious Cryptography” by Jean-Philippe Aumasson
What you’ll build: AES-128 with ECB and CBC modes, matching NIST vectors.
Why it teaches cryptography: You implement S-boxes, MixColumns (finite field math), and key expansion, then observe why modes control security.
Core challenges you’ll face:
- Rijndael S-box generation
- MixColumns in GF(2^8)
- Key schedule correctness
- IV handling and CBC chaining
Real World Outcome
What you will see:
- AES encryption that matches NIST test vectors
- ECB mode showing visible patterns
- CBC mode hiding structure
Command Line Outcome Example:
$ ./aes encrypt --mode ecb --key 00112233445566778899aabbccddeeff \
--in penguin.bmp --out penguin.ecb.bmp
$ ./aes encrypt --mode cbc --key 00112233445566778899aabbccddeeff \
--iv 000102030405060708090a0b0c0d0e0f --in penguin.bmp --out penguin.cbc.bmp
$ ./aes test-vectors
AES-128 ECB: PASS
AES-128 CBC: PASS
The Core Question You’re Answering
“How can simple byte-level operations create strong diffusion and confusion?”
AES shows how mixing, substitution, and key scheduling turn simple steps into strong security.
Concepts You Must Understand First
- Finite field arithmetic (GF(2^8))
- Why are bytes treated as polynomials?
- Book Reference: “Understanding Cryptography” Ch. 4
- Block cipher modes
- Why is ECB insecure?
- Book Reference: “Serious Cryptography” Ch. 3
- Key schedule
- Why must each round key be different?
- Book Reference: “Serious Cryptography” Ch. 3
Questions to Guide Your Design
- Will you generate the S-box or hardcode it?
- How will you structure the 4x4 state matrix?
- How will you handle padding for CBC mode?
Thinking Exercise
The Penguin Test
Why does encrypting a bitmap in ECB mode still show the penguin? What does that reveal about block ciphers?
The Interview Questions They’ll Ask
- Why is AES considered secure?
- What is the role of MixColumns?
- Why is ECB mode insecure?
- How does CBC introduce dependency between blocks?
- What is an IV and why must it be random?
Hints in Layers
Hint 1: Represent state as 4x4
uint8_t state[4][4];
Hint 2: Build MixColumns using GF multiply
Use xtime() to multiply by 2 in GF(2^8).
Hint 3: Test each round Compare intermediate state with known vectors.
Hint 4: Verify with OpenSSL
$ openssl enc -aes-128-ecb -K <hexkey> -in in.bin -nopad -nosalt
Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| AES design | “Serious Cryptography” | Ch. 3 |
| Galois fields | “Understanding Cryptography” | Ch. 4 |
Common Pitfalls & Debugging
Problem: “Test vectors fail”
- Why: Incorrect byte order or key schedule
- Fix: Validate S-box and key expansion first
Problem: “CBC decryption fails”
- Why: IV handling wrong
- Fix: Apply XOR with previous ciphertext block before decrypt
Definition of Done
- AES-128 ECB matches NIST test vectors
- AES-128 CBC matches NIST test vectors
- ECB image shows visible structure
- CBC image hides structure
Project 5: Secure Password Manager
- Main Programming Language: C
- Alternative Programming Languages: Rust, Go
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 2. The “Micro-SaaS / Pro Tool”
- Difficulty: Level 3: Advanced
- Knowledge Area: Cryptography / Security Engineering
- Software or Tool: KDF + AEAD
- Main Book: “Serious Cryptography” by Jean-Philippe Aumasson
What you’ll build: A local password manager that encrypts a vault with a master password using a KDF and AEAD.
Why it teaches cryptography: You must compose primitives safely: KDF + random nonce + authenticated encryption + memory hygiene.
Core challenges you’ll face:
- KDF parameter tuning
- AEAD encryption/decryption
- Secure random nonce generation
- Secure memory handling
Real World Outcome
What you will see:
- A vault file encrypted with your master password
- Tamper detection when the vault is modified
- A CLI for init/add/get/list
Command Line Outcome Example:
$ ./vault init --path ./vault.db
Vault initialized
$ ./vault add --site example.com --user alice --pass "p@ssw0rd"
Entry stored: example.com
$ ./vault list
- example.com (alice)
$ ./vault get --site example.com
Password: p@ssw0rd
$ ./vault get --site example.com --password wrong
ERROR: authentication failed (bad tag)
The Core Question You’re Answering
“How do you turn a weak human password into strong, safe encryption?”
This project forces you to think about KDF cost, nonce discipline, and tamper detection.
Concepts You Must Understand First
- KDF work factors
- How do time and memory cost slow attackers?
- Book Reference: “Serious Cryptography” Ch. 7
- AEAD nonces
- Why must nonces be unique?
- Book Reference: “Serious Cryptography” Ch. 7
- Secure memory handling
- Why must secrets be zeroized?
- Book Reference: “Effective C” Ch. 5-7
Questions to Guide Your Design
- Will you implement AEAD yourself or use a reference library?
- How will you store metadata (salt, nonce, version)?
- How will you prevent rollback attacks on the vault?
Thinking Exercise
The Stolen Vault
If an attacker steals your vault file, what is their best strategy to crack it? How does your KDF design slow them?
The Interview Questions They’ll Ask
- Why is KDF required for password storage?
- What happens if you reuse a nonce in AES-GCM?
- How do you design an encrypted file format?
- How do you prevent offline brute force?
- What is the difference between encryption and authentication?
Hints in Layers
Hint 1: Start with libsodium for AEAD
Use crypto_aead_chacha20poly1305_ietf_* as a reference.
Hint 2: Vault file structure
[magic][version][salt][kdf_params][nonce][ciphertext][tag]
Hint 3: Constant-time compare Always compare tags using a constant-time function.
Hint 4: Test failure paths Modify one byte of ciphertext and ensure decryption fails.
Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| KDF / password hardening | “Serious Cryptography” | Ch. 7 |
| Secure coding | “Effective C” | Ch. 5-7 |
Common Pitfalls & Debugging
Problem: “Wrong password still decrypts”
- Why: Tag not checked or ignored
- Fix: Treat tag mismatch as a hard failure
Problem: “Same password produces same ciphertext”
- Why: Nonce reuse or missing salt
- Fix: Generate fresh salt and nonce per vault
Definition of Done
- Vault fails to decrypt with wrong password
- Tampered ciphertext fails integrity check
- Nonce and salt are randomized per vault
- Sensitive memory is wiped after use
Project 6: Diffie-Hellman Key Exchange Visualizer
- Main Programming Language: Python
- Alternative Programming Languages: JavaScript
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: Key Exchange
- Software or Tool: Diffie-Hellman
- Main Book: “Understanding Cryptography” by Paar & Pelzl
What you’ll build: A visual simulator of Diffie-Hellman that shows public values, shared secret derivation, and optional man-in-the-middle attack.
Why it teaches cryptography: It makes an abstract protocol visible. You see exactly why exchanging g^a and g^b yields the same secret.
Core challenges you’ll face:
- Big integer math
- Visualizing the handshake
- Simulating MITM
Real World Outcome
What you will see:
- Step-by-step exchange between Alice and Bob
- Derived shared secret matches
- MITM mode shows split secrets
Command Line Outcome Example:
$ python3 dhviz.py --p 23 --g 5 --alice 6 --bob 15
Alice sends: 5^6 mod 23 = 8
Bob sends: 5^15 mod 23 = 19
Shared secret (Alice): 2
Shared secret (Bob): 2
$ python3 dhviz.py --mitm
MITM active: Alice<->Mallory secret != Bob<->Mallory secret
The Core Question You’re Answering
“How can two parties agree on a secret that never crosses the wire?”
Diffie-Hellman is the foundation of forward secrecy in TLS and modern secure messaging.
Concepts You Must Understand First
- Modular exponentiation
- Why is it fast for the defender but hard for attacker?
- Book Reference: “Understanding Cryptography” Ch. 11
- Discrete log hardness
- Why is reversing g^a mod p hard?
- Book Reference: “Understanding Cryptography” Ch. 11
- MITM threat model
- Why is DH alone not authenticating?
- Book Reference: “Foundations of Information Security” Ch. 2
Questions to Guide Your Design
- How will you represent primes and generators visually?
- What does a “step” in the protocol mean in your UI?
- How will you show MITM without confusing users?
Thinking Exercise
The MITM Swap
If Mallory intercepts both public values, why does she end up with two different shared secrets? What would fix this?
The Interview Questions They’ll Ask
- Why does DH provide secrecy but not authentication?
- What is forward secrecy?
- How does ECDH differ from DH?
- Why must p be prime?
- How does TLS prevent MITM?
Hints in Layers
Hint 1: Small primes for visualization Start with tiny primes so you can print all steps.
Hint 2: Separate math from UI Implement DH as a library, then build visualization on top.
Hint 3: MITM mode Replace Bob’s public value with Mallory’s and show divergence.
Hint 4: Show the transcript Print each message as a line with arrows.
Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Diffie-Hellman | “Understanding Cryptography” | Ch. 11 |
| Threat models | “Foundations of Information Security” | Ch. 1-2 |
Common Pitfalls & Debugging
Problem: “Secrets don’t match”
- Why: Incorrect modulo arithmetic
- Fix: Verify pow(a, b, p) matches both sides
Problem: “MITM still shows same secret”
- Why: You didn’t actually substitute public values
- Fix: Insert Mallory’s public key in both directions
Definition of Done
- Alice and Bob compute identical secrets
- MITM mode produces different secrets
- Visualization shows each protocol step clearly
Project 7: TLS 1.3 Handshake Simulator
- Main Programming Language: Go
- Alternative Programming Languages: Rust, Python
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 2. The “Micro-SaaS / Pro Tool”
- Difficulty: Level 3: Advanced
- Knowledge Area: Protocol Security
- Software or Tool: TLS 1.3
- Main Book: “Serious Cryptography” by Jean-Philippe Aumasson
What you’ll build: A simplified TLS 1.3 handshake simulator that models key exchange, certificate verification, and session key derivation.
Why it teaches cryptography: It connects primitives to real protocols and shows how key schedules, transcripts, and signatures prevent downgrade and MITM.
Core challenges you’ll face:
- Transcript hashing
- Certificate chain validation
- Key schedule derivation (HKDF)
- State machine correctness
Real World Outcome
What you will see:
- Handshake transcript printed step by step
- Matching client/server session keys
- Failure when certificates are invalid or transcript is modified
Command Line Outcome Example:
$ ./tls13-sim --mode client --server localhost
[client] ClientHello ->
[server] ServerHello <-
[server] Certificate <-
[client] CertificateVerify <-
[client] Finished <-
[server] Finished ->
Handshake complete: session key = 9f3b...a1
$ ./tls13-sim --break-transcript
ERROR: transcript hash mismatch
The Core Question You’re Answering
“How do primitives combine to create a secure, negotiated session?”
TLS is where theory meets practice: if any step is wrong, security collapses.
Concepts You Must Understand First
- HKDF
- How does HKDF expand secrets?
- Book Reference: “Serious Cryptography” Ch. 6
- Transcript hashing
- Why does every message get hashed?
- Book Reference: RFC 8446 Sections 4-7
- Certificate validation
- Why is the CA chain critical?
- Book Reference: “Foundations of Information Security” Ch. 7
Questions to Guide Your Design
- What is the minimal handshake you can simulate correctly?
- How will you represent handshake state transitions?
- How will you verify transcript integrity?
Thinking Exercise
Downgrade Attack
If the attacker removes “TLS 1.3” from ClientHello, what must the server do to detect it?
The Interview Questions They’ll Ask
- What does TLS 1.3 change compared to TLS 1.2?
- What is a transcript hash and why is it important?
- How does TLS 1.3 achieve forward secrecy?
- Why are cipher suites different in TLS 1.3?
- How does the Finished message prevent tampering?
Hints in Layers
Hint 1: Model messages as structs Serialize each handshake message into bytes.
Hint 2: Hash the transcript Update a SHA-256 context after every handshake message.
Hint 3: HKDF is just HMAC Implement HKDF using your HMAC and SHA-256.
Hint 4: Break things on purpose Flip one bit in ServerHello and confirm the handshake fails.
Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| TLS overview | RFC 8446 | Sections 4-7 |
| HKDF & HMAC | “Serious Cryptography” | Ch. 6 |
| Certificates | “Foundations of Information Security” | Ch. 7 |
Common Pitfalls & Debugging
Problem: “Client and server keys differ”
- Why: Transcript or HKDF inputs mismatched
- Fix: Log every transcript hash input
Problem: “Handshake succeeds even when altered”
- Why: You skipped transcript validation
- Fix: Verify Finished message using transcript hash
Definition of Done
- Client and server derive identical session keys
- Certificate validation fails for untrusted CA
- Transcript hash changes with any message change
- Broken-handshake mode demonstrates failure
Project Comparison Table
| # | Project Name | Difficulty | Time | Depth of Understanding | Fun Factor |
|---|---|---|---|---|---|
| 1 | Classic Cipher Toolkit | Beginner | Weekend | Medium | High |
| 2 | SHA-256 From Scratch | Intermediate | 1-2 weeks | High | Medium |
| 3 | RSA Implementation | Intermediate | 2-3 weeks | High | Medium |
| 4 | AES-128 Implementation | Advanced | 2-3 weeks | Very High | Medium |
| 5 | Secure Password Manager | Advanced | 2-3 weeks | Very High | High |
| 6 | Diffie-Hellman Visualizer | Intermediate | 1 week | High | High |
| 7 | TLS 1.3 Simulator | Advanced | 2-3 weeks | Very High | Very High |
Recommended Order: 1 -> 2 -> 4 -> 3 -> 6 -> 7 -> 5