General Cryptography: Zero to Hero
A progressive guide from fundamental concepts to advanced cryptographic mechanisms.
Roadmap
| Level | Topic | Core Concept |
|---|---|---|
| 0 | Why Cryptography? | The problem space |
| 1 | Symmetric Encryption | One key, two operations |
| 2 | Randomness & Salts | Unpredictability as security |
| 3 | Key Derivation Functions | Turning passwords into keys |
| 4 | Authenticated Encryption | Confidentiality + Integrity |
| 5 | Asymmetric Encryption | Public/private key pairs |
| 6 | Digital Signatures | Proving authenticity |
| 7 | Key Exchange | Establishing shared secrets |
| 8 | Key Encapsulation | Post-quantum key establishment |
Level 0: Why Cryptography?
The Problem
You want to send a message that only the intended recipient can read—even if an adversary intercepts it.
Alice ----[message]----> Eve (intercepting) ----[message]----> Bob
Without cryptography: Eve reads everything.
With cryptography: Eve sees gibberish.
The Three Pillars
| Property | Question Answered | Threat Mitigated |
|---|---|---|
| Confidentiality | Can only authorized parties read it? | Eavesdropping |
| Integrity | Has the data been tampered with? | Modification |
| Authenticity | Who sent this? | Impersonation |
Key Insight
Cryptography doesn’t hide that communication happened—it protects what was communicated. Metadata (who, when, how much) often remains visible.
Level 1: Symmetric Encryption
The Model
One secret key. Two operations: encrypt and decrypt.
plaintext --[encrypt(key)]--> ciphertext --[decrypt(key)]--> plaintext
The key problem: Both parties must possess the same secret key. How do they share it securely? (Solved later in Levels 5-8)
Core Algorithms
| Algorithm | Type | Status |
|---|---|---|
| AES-256 | Block cipher | Standard, use this |
| ChaCha20 | Stream cipher | Modern alternative |
| 3DES | Block cipher | Legacy, avoid |
Modes of Operation
Block ciphers encrypt fixed-size blocks. Modes define how to handle arbitrary-length data.
| Mode | Parallelizable | Auth | Notes |
|---|---|---|---|
| ECB | Yes | No | Never use - patterns leak |
| CBC | Encrypt: No | No | Requires padding, IV |
| CTR | Yes | No | Turns block cipher into stream |
| GCM | Yes | Yes | Recommended - authenticated |
The Nonce/IV Rule
Never reuse a nonce with the same key.
Nonce reuse can catastrophically break security—from revealing XOR of plaintexts (CTR) to enabling forgeries (GCM).
Level 2: Randomness & Salts
What is a Salt?
A salt is a random value added to input data before hashing or key derivation. Its purpose: ensure identical inputs produce different outputs.
# Without salt: identical passwords = identical hashes
hash("password123") # Always the same
# With salt: identical passwords = different hashes
hash("password123" + salt_A) # Unique output A
hash("password123" + salt_B) # Unique output BWhy Salts Exist
- Defeat Rainbow Tables - Precomputed hash tables become useless
- Prevent Identical Hash Detection - Same password ≠ same hash
- Increase Attack Cost - Each hash must be cracked individually
Salt vs. Nonce vs. IV vs. Pepper
| Value | Purpose | Secret? | Unique Per |
|---|---|---|---|
| Salt | Randomize KDF/hash input | No | Per password/key |
| Nonce | Ensure unique ciphertext | No | Per encryption |
| IV | Initialize cipher state | No | Per encryption |
| Pepper | Additional secret input | Yes | Global/per-app |
Critical Requirements
import os
import secrets
# ✓ Correct: Cryptographically random, sufficient length
salt = os.urandom(32)
salt = secrets.token_bytes(32)
# ✗ Wrong: Predictable PRNG
import random
salt = random.randbytes(32) # Insecure!Storage: Salt is NOT secret. Store it alongside the derived output.
Level 3: Key Derivation Functions (KDFs)
The Problem
Users provide passwords. Cryptography needs keys.
- Passwords: Variable length, low entropy, human-memorable
- Keys: Fixed length, high entropy, random-looking
The Solution
KDFs transform passwords into keys through deliberate computational expense.
password + salt --[KDF]--> key
Common KDFs
| KDF | Cost Type | Recommended Params (2024) |
|---|---|---|
| PBKDF2 | CPU (iterations) | 600,000+ iterations, SHA-256 |
| scrypt | CPU + Memory | N=2^17, r=8, p=1 |
| Argon2id | CPU + Memory + Parallelism | Preferred for new systems |
Why “Slow” is a Feature
Fast hash: Attacker tests 10 billion passwords/second
PBKDF2 (600k iter): Attacker tests ~1,600 passwords/second
Slowness is the security.
Level 4: Authenticated Encryption
The Problem with “Just Encryption”
Basic encryption provides confidentiality but not integrity. An attacker can: - Flip bits in ciphertext (causes predictable plaintext changes) - Truncate or reorder encrypted blocks - Substitute ciphertext from other messages
You won’t know the data was tampered with.
AEAD: Authenticated Encryption with Associated Data
Combines encryption + authentication in one operation.
(plaintext, aad) + key + nonce --[AEAD.encrypt]--> ciphertext + tag
ciphertext + tag + aad + key + nonce --[AEAD.decrypt]--> plaintext OR rejection
AAD (Associated Data): Authenticated but not encrypted. Useful for headers, metadata.
Recommended Algorithms
| Algorithm | Notes |
|---|---|
| AES-256-GCM | Industry standard, hardware-accelerated |
| ChaCha20-Poly1305 | Software-friendly, constant-time |
| XChaCha20-Poly1305 | Extended nonce (192-bit), safer for random nonces |
The Golden Rule
Always use authenticated encryption. If you’re using AES-CBC or raw AES-CTR, you’re probably doing it wrong.
Level 5: Asymmetric Encryption
The Key Distribution Problem (Solved)
Symmetric encryption requires sharing a secret key. But how do you share a secret with someone you’ve never met?
Asymmetric cryptography: Two mathematically linked keys. - Public key: Share with everyone - Private key: Keep secret
The Model
Alice's public key --[encrypt]--> ciphertext
Alice's private key --[decrypt]--> plaintext
Anyone can encrypt to Alice. Only Alice can decrypt.
Core Algorithms
| Algorithm | Based On | Status |
|---|---|---|
| RSA | Integer factorization | Legacy, use ≥3072 bits |
| ECIES | Elliptic curves | Modern, smaller keys |
| X25519 + AEAD | Curve25519 | Recommended |
The Catch
Asymmetric encryption is slow (~1000x slower than AES). Real systems use hybrid encryption:
1. Generate random symmetric key
2. Encrypt data with symmetric key (fast)
3. Encrypt symmetric key with recipient's public key (slow, but small)
4. Send both
Level 6: Digital Signatures
The Problem
Encryption ensures only the recipient reads the message. But how does the recipient know who sent it?
The Model (Reversed from Encryption)
Alice's private key --[sign]----> signature
Alice's public key --[verify]--> valid/invalid
Anyone can verify. Only Alice can sign.
Properties
| Property | Meaning |
|---|---|
| Authenticity | Signature proves Alice signed it |
| Integrity | Any modification invalidates signature |
| Non-repudiation | Alice cannot deny signing (she has the only private key) |
Core Algorithms
| Algorithm | Notes |
|---|---|
| Ed25519 | Recommended - fast, secure, small signatures |
| ECDSA | Widely deployed (Bitcoin, TLS), more complex |
| RSA-PSS | Legacy compatibility |
Sign-then-Encrypt vs. Encrypt-then-Sign
- Sign-then-Encrypt: Recipient knows who sent it, but can’t prove it to others
- Encrypt-then-Sign: Anyone can see who sent it (signature is public)
Choose based on your threat model.
Level 7: Key Exchange
The Problem
Two parties want to establish a shared secret over an insecure channel—without any prior shared secrets.
Diffie-Hellman Key Exchange
The foundational algorithm (1976). Both parties contribute randomness; both derive the same shared secret.
Alice: generates a (private), computes A (public)
Bob: generates b (private), computes B (public)
Exchange public values over insecure channel
Alice: computes shared_secret from (a, B)
Bob: computes shared_secret from (b, A)
Result: Both have identical shared_secret. Eve (watching) cannot compute it.
Modern Implementations
| Algorithm | Notes |
|---|---|
| X25519 | Recommended - Curve25519 ECDH |
| ECDH (P-256) | NIST curve, widely supported |
| DH (finite field) | Classical, requires large parameters |
From Exchange to Encryption
Key exchange produces raw shared secret. Derive actual keys via KDF:
shared_secret --[HKDF]--> encryption_key, mac_key, etc.
Level 8: Key Encapsulation (KEMs)
Key Exchange vs. Key Encapsulation
| Mechanism | Flow | Output |
|---|---|---|
| Key Exchange | Interactive (both parties contribute) | Shared secret |
| Key Encapsulation | One-way (sender to recipient) | Encapsulated key |
KEMs are simpler: recipient publishes public key, sender generates + encapsulates a random key.
The KEM Model
Recipient: (public_key, private_key) = KEM.keygen()
Sender: (ciphertext, shared_key) = KEM.encapsulate(public_key)
sends ciphertext to recipient
Recipient: shared_key = KEM.decapsulate(private_key, ciphertext)
Both parties now have shared_key. Use it with symmetric AEAD.
Why KEMs Matter: Post-Quantum Cryptography
Quantum computers threaten RSA, ECDH, and ECDSA. KEMs provide a clean abstraction for quantum-resistant algorithms.
| Algorithm | Type | Status |
|---|---|---|
| ML-KEM (Kyber) | Lattice-based | NIST standard (2024) |
| Classic McEliece | Code-based | Large keys, high confidence |
| BIKE, HQC | Code-based | Alternate candidates |
Hybrid Approach (Recommended)
Combine classical + post-quantum for defense in depth:
X25519 shared_secret || ML-KEM shared_secret --[HKDF]--> final_key
If either holds, security is preserved.
What’s Next?
Putting It Together
A modern secure channel typically combines:
Level 8: KEM (establish shared secret)
└─→ Level 3: KDF (derive session keys)
└─→ Level 4: AEAD (encrypt application data)
└─→ Level 6: Signatures (authenticate endpoints)
PyCryption Experiments
Use this repository to explore each level hands-on:
| Notebook | Relevant Levels |
|---|---|
Symmetric.ipynb |
1, 2, 3, 4 |
Asymmetric.ipynb |
5, 6, 7 |
ML-KEM.ipynb |
8 |
Encryption Composer.ipynb |
All (composition) |
Further Reading
- Serious Cryptography by Jean-Philippe Aumasson
- Cryptography Engineering by Ferguson, Schneier, Kohno
- NIST Post-Quantum Cryptography standards (FIPS 203, 204, 205)