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 B

Why Salts Exist

  1. Defeat Rainbow Tables - Precomputed hash tables become useless
  2. Prevent Identical Hash Detection - Same password ≠ same hash
  3. 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.

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

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)
Back to top