← Back to all projects

TOR ANONYMITY NETWORKS DEEP DIVE PROJECTS

Tor & Anonymity Networks Deep Dive: Onion Routing to Hidden Services

Goal: Truly understand how Tor works—from layered encryption to hidden services—by building tools that implement the core concepts of anonymity networks. Learn why Tor provides stronger protection than VPNs and how .onion sites achieve server anonymity.


Core Concept Analysis

VPN vs Tor: The Fundamental Difference

Before diving into projects, understand this critical distinction:

╔═══════════════════════════════════════════════════════════════════════════════╗
║                           VPN ARCHITECTURE                                     ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║                                                                                ║
║   [You] ──encrypted──> [VPN Server] ──plaintext──> [Destination]              ║
║     │                       │                            │                     ║
║     │                       │                            │                     ║
║   Your IP              VPN knows:                   Sees VPN IP                ║
║   hidden               • Your real IP              as origin                   ║
║   from                 • Your destination                                      ║
║   destination          • All your traffic                                      ║
║                        • Timing of everything                                  ║
║                                                                                ║
║   SINGLE POINT OF TRUST: VPN provider knows EVERYTHING                        ║
║                                                                                ║
╚═══════════════════════════════════════════════════════════════════════════════╝

╔═══════════════════════════════════════════════════════════════════════════════╗
║                           TOR ARCHITECTURE                                     ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║                                                                                ║
║   [You] ──────> [Guard] ──────> [Middle] ──────> [Exit] ──────> [Destination] ║
║     │              │               │               │                │          ║
║     │              │               │               │                │          ║
║   Knows:        Knows:          Knows:          Knows:           Knows:       ║
║   Guard IP      Your IP         Guard IP        Middle IP        Exit IP      ║
║   only          Next hop        Next hop        Destination      only         ║
║                 (Middle)        (Exit)          Content                        ║
║                                                                                ║
║   DISTRIBUTED TRUST: No single node knows both origin AND destination         ║
║                                                                                ║
╚═══════════════════════════════════════════════════════════════════════════════╝

Why This Matters

Aspect VPN Tor
Trust Model Single point (VPN provider) Distributed (3+ nodes)
IP Hiding VPN knows your real IP No single node knows both ends
Logging Risk VPN can log everything Would need to compromise multiple nodes
Speed Fast (single hop) Slower (3+ hops)
Encryption Single layer Multiple layers (onion)
Hidden Services Not possible .onion addresses
Best For Privacy from destination Anonymity from everyone

The Onion Routing Concept

SENDING A MESSAGE THROUGH TOR:

Step 1: Encrypt for Exit node
┌──────────────────────────────────────────────────────────┐
│  Encrypt_Exit( "GET /page HTTP/1.1\nHost: example.com" ) │
└──────────────────────────────────────────────────────────┘
                              ↓
Step 2: Wrap with Middle layer
┌──────────────────────────────────────────────────────────────┐
│  Encrypt_Middle( "Forward to Exit" + [Exit-encrypted data] ) │
└──────────────────────────────────────────────────────────────┘
                              ↓
Step 3: Wrap with Guard layer (outermost)
┌────────────────────────────────────────────────────────────────┐
│  Encrypt_Guard( "Forward to Middle" + [Middle-encrypted data] )│
└────────────────────────────────────────────────────────────────┘
                              ↓
Final packet looks like:
┌─────────────────────────────────────────────────────────────────┐
│ ████████████████████████████████████████████████████████████████│
│ █ Guard can decrypt: sees "Forward to Middle" + encrypted blob █│
│ █ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ █│
│ █ ▓ Middle can decrypt: sees "Forward to Exit" + encrypted ▓ █│
│ █ ▓ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ▓ █│
│ █ ▓ ░ Exit can decrypt: sees actual HTTP request          ░ ▓ █│
│ █ ▓ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ▓ █│
│ █ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ █│
│ ████████████████████████████████████████████████████████████████│
└─────────────────────────────────────────────────────────────────┘

Why .onion Sites Exist (Hidden Services)

Normal websites reveal their IP address. Hidden services solve this:

NORMAL WEBSITE:
  Browser → DNS lookup → Gets IP 93.184.216.34 → Connects directly

  Problem: Everyone knows the server's IP. Can be:
    • Traced
    • Blocked
    • DDoS attacked
    • Raided by authorities

HIDDEN SERVICE (.onion):
  Browser → No DNS → Uses rendezvous point → Server's IP never revealed

  How it works:
  1. Server connects to "Introduction Points" via Tor circuits
  2. Client gets .onion address (hash of server's public key)
  3. Client picks a "Rendezvous Point"
  4. Client tells server (via Introduction Point) to meet at Rendezvous
  5. Both connect to Rendezvous via separate Tor circuits
  6. Traffic flows: Client ← Tor → Rendezvous ← Tor → Server

  Neither knows the other's IP!

┌─────────────────────────────────────────────────────────────────────────────┐
│                        HIDDEN SERVICE PROTOCOL                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│                         [Introduction Points]                                │
│                              ▲       ▲                                       │
│                             /         \                                      │
│                    (Tor Circuit)    (Tor Circuit)                           │
│                           /             \                                    │
│                          /               \                                   │
│    [Client] ─────────────                 ─────────────> [Hidden Server]    │
│        │                                                        │            │
│        │                                                        │            │
│        └────── (Tor Circuit) ──> [Rendezvous] <── (Tor Circuit) ┘           │
│                                   Point                                      │
│                                                                              │
│    Total path: 6 relays (3 client-side + 3 server-side)                     │
│    Neither party reveals their IP to anyone                                  │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

Key Tor Components

Component Role Your Project Will Build
Onion Routing Layered encryption through multiple hops Projects 1, 2, 3
Circuits Paths through the network Projects 4, 5
Cells Fixed-size data units (512 bytes) Project 6
Directory Authorities Trusted nodes that publish network state Project 7
Guard Nodes Entry points (used for 2-3 months) Project 8
Exit Nodes Where traffic leaves Tor network Project 9
Hidden Services .onion sites with server anonymity Projects 12, 13
Rendezvous Points Meeting points for hidden services Project 14

Project 1: Layered Encryption Simulator

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust, C
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold” (Educational/Personal Brand)
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Cryptography / Onion Routing
  • Software or Tool: Encryption Simulator
  • Main Book: “Serious Cryptography, 2nd Edition” by Jean-Philippe Aumasson

What you’ll build: A command-line tool that demonstrates onion encryption—wrapping a message in multiple encryption layers and then unwrapping them one by one, simulating how data flows through a Tor circuit.

Why it teaches Tor: This is the fundamental concept of onion routing. You’ll see exactly how each relay can only decrypt its layer and why no single node can read the original message or know both endpoints.

Core challenges you’ll face:

  • Symmetric encryption with unique keys → maps to per-hop session keys
  • Layer ordering → maps to correct encryption/decryption sequence
  • Key distribution simulation → maps to how Tor establishes keys
  • Handling metadata (next hop address) → maps to routing information

Key Concepts:

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Basic cryptography concepts, symmetric encryption

Real world outcome:

$ ./onion-encrypt --message "Secret message to destination" \
    --keys guard.key middle.key exit.key

╔═══════════════════════════════════════════════════════════════╗
║                    ONION ENCRYPTION DEMO                       ║
╚═══════════════════════════════════════════════════════════════╝

Original message: "Secret message to destination"

Step 1: Encrypt for EXIT node (innermost layer)
  Key: exit.key (AES-256)
  Plaintext: "DEST:example.com|Secret message to destination"
  Ciphertext: 7f3a9b2c...d4e1 (48 bytes)

Step 2: Encrypt for MIDDLE node
  Key: middle.key (AES-256)
  Plaintext: "NEXT:exit_node|7f3a9b2c...d4e1"
  Ciphertext: 2b8c4f1a...9e7d (64 bytes)

Step 3: Encrypt for GUARD node (outermost layer)
  Key: guard.key (AES-256)
  Plaintext: "NEXT:middle_node|2b8c4f1a...9e7d"
  Ciphertext: 9a1d3e5f...c2b8 (80 bytes)

Final onion: 9a1d3e5f...c2b8
Layers: 3
Total size: 80 bytes

$ ./onion-decrypt --onion 9a1d3e5f...c2b8 --node guard

╔═══════════════════════════════════════════════════════════════╗
║                 GUARD NODE DECRYPTION                          ║
╚═══════════════════════════════════════════════════════════════╝

Received onion: 9a1d3e5f...c2b8 (80 bytes)
Decrypting with guard.key...

Result:
  Next hop: middle_node
  Remaining onion: 2b8c4f1a...9e7d (64 bytes)

Guard knows:
  ✓ Previous hop (client IP)
  ✓ Next hop (middle_node)
  ✗ Final destination (hidden in inner layers)
  ✗ Message content (hidden in inner layers)

Forwarding to: middle_node

$ ./onion-decrypt --onion 2b8c4f1a...9e7d --node middle
[... continues through each layer ...]

$ ./onion-decrypt --onion 7f3a9b2c...d4e1 --node exit

╔═══════════════════════════════════════════════════════════════╗
║                  EXIT NODE DECRYPTION                          ║
╚═══════════════════════════════════════════════════════════════╝

Received onion: 7f3a9b2c...d4e1 (48 bytes)
Decrypting with exit.key...

Result:
  Destination: example.com
  Message: "Secret message to destination"

Exit knows:
  ✓ Previous hop (middle_node)
  ✓ Final destination (example.com)
  ✓ Message content (if not HTTPS)
  ✗ Original sender (hidden by previous layers)

Implementation Hints: Use AES-256 in CTR or CBC mode. Each layer includes routing metadata (next hop) plus the encrypted inner payload. Structure: [next_hop_id:16bytes][encrypted_inner_data]. The outermost layer goes to the guard, who decrypts to find middle’s address + still-encrypted data. Each node “peels” one layer. Demonstrate that no single node sees both the source and final destination.

Learning milestones:

  1. Encrypt/decrypt single layer → You understand symmetric encryption
  2. Chain multiple layers correctly → You understand onion structure
  3. Show what each node can/cannot see → You understand Tor’s privacy model

Project 2: Diffie-Hellman Key Exchange Demo

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust, C
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Cryptography / Key Exchange
  • Software or Tool: Key Exchange Demo
  • Main Book: “Serious Cryptography, 2nd Edition” by Jean-Philippe Aumasson

What you’ll build: An implementation of both classic Diffie-Hellman and Curve25519 (X25519) key exchange, demonstrating how Tor establishes shared secrets with each relay without any eavesdropper being able to derive the key.

Why it teaches Tor: Tor’s ntor handshake uses Curve25519 for key exchange. Understanding how two parties can agree on a secret over a public channel—and why this provides forward secrecy—is fundamental to understanding Tor’s security.

Core challenges you’ll face:

  • Modular exponentiation (classic DH) → maps to mathematical foundations
  • Elliptic curve operations (X25519) → maps to modern Tor crypto
  • Man-in-the-middle prevention → maps to authenticated key exchange
  • Forward secrecy demonstration → maps to ephemeral keys

Key Concepts:

  • Diffie-Hellman: “Serious Cryptography, 2nd Edition” Chapter 10 - Aumasson
  • Elliptic Curve Cryptography: “Serious Cryptography, 2nd Edition” Chapter 11 - Aumasson
  • Tor’s ntor Protocol: Tor Specifications - ntor handshake
  • Curve25519: “Tor Key Creation - Curve25519”

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Basic number theory, modular arithmetic

Real world outcome:

$ ./key-exchange --mode classic-dh --demo

╔═══════════════════════════════════════════════════════════════╗
║           CLASSIC DIFFIE-HELLMAN KEY EXCHANGE                  ║
╚═══════════════════════════════════════════════════════════════╝

Public parameters (known to everyone, including attackers):
  Prime (p): 23 (small for demo; real: 2048+ bits)
  Generator (g): 5

ALICE (Client):
  Private key (a): 6 (secret, never transmitted)
  Public key (A): g^a mod p = 5^6 mod 23 = 8
  → Sends A=8 to Bob

BOB (Relay):
  Private key (b): 15 (secret, never transmitted)
  Public key (B): g^b mod p = 5^15 mod 23 = 19
  → Sends B=19 to Alice

KEY DERIVATION:
  Alice computes: B^a mod p = 19^6 mod 23 = 2
  Bob computes:   A^b mod p = 8^15 mod 23 = 2

  SHARED SECRET: 2 ✓ (identical!)

WHAT AN EAVESDROPPER SEES:
  • p=23, g=5 (public parameters)A=8 (Alice's public key)
  • B=19 (Bob's public key)

  Cannot compute shared secret without:
  • Alice's private key (a=6), or
  • Bob's private key (b=15)

  This is the "Discrete Logarithm Problem" - computationally hard!

$ ./key-exchange --mode x25519 --demo

╔═══════════════════════════════════════════════════════════════╗
║           X25519 (CURVE25519) KEY EXCHANGE                     ║
║              Used in Tor's ntor handshake                      ║
╚═══════════════════════════════════════════════════════════════╝

ALICE (Client):
  Private key: 77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a
  Public key:  8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a
  → Sends public key to Bob

BOB (Relay):
  Private key: 5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb
  Public key:  de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f
  → Sends public key to Alice

SHARED SECRET COMPUTATION:
  Alice: X25519(alice_private, bob_public)
  Bob:   X25519(bob_private, alice_public)

  Result: 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742 ✓

FORWARD SECRECY DEMONSTRATION:
  If we use EPHEMERAL keys (new keys each session):
  → Compromising today's key doesn't reveal past sessions
  → Compromising long-term key doesn't reveal session keys

  Tor generates fresh ephemeral keys for EVERY circuit!

Implementation Hints: For classic DH, implement modular exponentiation with big integers. For X25519, you can use a library (cryptography.io in Python) or implement the curve operations yourself for deeper understanding. Show the mathematical relationship: g^(a*b) = (g^a)^b = (g^b)^a. Demonstrate that knowing only g^a and g^b doesn’t reveal g^(a*b) without solving the discrete log problem.

Learning milestones:

  1. Classic DH with small numbers → You understand the math
  2. X25519 key exchange → You understand modern Tor crypto
  3. Demonstrate forward secrecy → You understand why Tor is secure against future key compromise

Project 3: Onion Routing Network Simulator

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Network Simulation / Anonymity
  • Software or Tool: Network Simulator
  • Main Book: “Computer Networks, 5th Edition” by Tanenbaum

What you’ll build: A complete simulation of onion routing with multiple nodes, where messages are encrypted in layers and routed through a path of relays—demonstrating exactly how anonymity is achieved.

Why it teaches Tor: This combines encryption (Project 1) and key exchange (Project 2) into a working system. You’ll see how circuits are built, how data flows, and what each node can observe.

Core challenges you’ll face:

  • Multi-node coordination → maps to distributed system basics
  • Circuit path selection → maps to Tor’s relay selection
  • Bidirectional communication → maps to responses traverse the same path
  • Timing and ordering → maps to cell-based transmission

Key Concepts:

Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: Projects 1 and 2, socket programming

Real world outcome:

$ ./onion-network --nodes 5 --start

╔═══════════════════════════════════════════════════════════════╗
║              ONION ROUTING NETWORK SIMULATOR                   ║
╚═══════════════════════════════════════════════════════════════╝

Starting 5 relay nodes...
  Node A (Guard-capable): localhost:9001 [ONLINE]
  Node B (Middle):        localhost:9002 [ONLINE]
  Node C (Middle):        localhost:9003 [ONLINE]
  Node D (Exit-capable):  localhost:9004 [ONLINE]
  Node E (Exit-capable):  localhost:9005 [ONLINE]

Network ready. Type 'help' for commands.

> build-circuit
Building 3-hop circuit...

Step 1: Connect to Guard (Node A)
  → TCP connect to localhost:9001
  → DH key exchange with A
  → Session key established: k_A = 3f7a...

Step 2: Extend to Middle (Node C) via Guard
  → Send EXTEND cell to A: "Connect to C"
  → A connects to C, performs DH on our behalf
  → Session key established: k_C = 8b2d...

Step 3: Extend to Exit (Node D) via A→C
  → Send EXTEND cell through A→C: "Connect to D"
  → C connects to D, performs DH on our behalf
  → Session key established: k_D = c4e9...

Circuit established: [Client] → A → C → D → [Internet]
Circuit ID: 0x7f3a

> send "GET / HTTP/1.1\nHost: example.com" --to example.com:80

Encrypting message for transmission...
  Layer 3 (Exit):   Encrypt("DEST:example.com:80|GET /...", k_D)
  Layer 2 (Middle): Encrypt("[encrypted layer 3]", k_C)
  Layer 1 (Guard):  Encrypt("[encrypted layer 2]", k_A)

Sending through circuit 0x7f3a...

[Node A - Guard] Received 512-byte cell
  → Decrypted with k_A
  → Found: RELAY cell for circuit 0x7f3a
  → Forwarding to Node C (still encrypted)

[Node C - Middle] Received 512-byte cell
  → Decrypted with k_C
  → Found: RELAY cell for circuit 0x7f3a
  → Forwarding to Node D (still encrypted)

[Node D - Exit] Received 512-byte cell
  → Decrypted with k_D
  → Found: DATA cell, destination example.com:80
  → Connecting to example.com:80...
  → Sending HTTP request

[Node D - Exit] Received response from example.com
  → Encrypting response with k_D
  → Sending back through circuit

[Response received at client]
HTTP/1.1 200 OK
Content-Type: text/html
...

> show-knowledge

╔═══════════════════════════════════════════════════════════════╗
║              WHAT EACH NODE KNOWS                              ║
╚═══════════════════════════════════════════════════════════════╝

Node A (Guard):
  ✓ Client's real IP address
  ✓ Next hop: Node C
  ✗ Final destination (encrypted)
  ✗ Message content (encrypted)
  ✗ That Node D is the exit

Node C (Middle):
  ✓ Previous hop: Node A
  ✓ Next hop: Node D
  ✗ Client's IP (only knows A)
  ✗ Final destination (encrypted)
  ✗ Message content (encrypted)

Node D (Exit):
  ✓ Previous hop: Node C
  ✓ Final destination: example.com
  ✓ Message content (if not HTTPS)
  ✗ Client's IP address
  ✗ That Node A is the guard

ANONYMITY ACHIEVED: No single node knows both origin and destination!

Implementation Hints: Run each “node” as a separate process or thread listening on a port. Implement circuit building with CREATE/CREATED cells and EXTEND/EXTENDED cells. Use fixed-size cells (512 bytes in real Tor) for traffic analysis resistance. For the simulation, each node maintains a table of circuit IDs to (session_key, next_hop) mappings. Bidirectional: responses travel the same circuit in reverse, each node adding its encryption layer.

Learning milestones:

  1. Build a circuit through 3 nodes → You understand circuit construction
  2. Send data and receive response → You understand bidirectional onion routing
  3. Demonstrate node knowledge isolation → You understand Tor’s security model

Project 4: Tor Directory Parser & Network Visualizer

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Network Analysis / Parsing
  • Software or Tool: Tor Directory Analyzer
  • Main Book: “TCP/IP Illustrated, Volume 1” by W. Richard Stevens

What you’ll build: A tool that downloads and parses the real Tor network consensus document, extracting information about all relays—their flags, bandwidth, exit policies—and visualizes the network.

Why it teaches Tor: The consensus document is how Tor clients learn about available relays. Understanding its structure teaches you how Tor maintains a global view of the network, how relays are classified (Guard, Exit, etc.), and how trust is established through directory authorities.

Core challenges you’ll face:

  • Fetching consensus from directory authorities → maps to Tor’s bootstrap process
  • Parsing the consensus format → maps to understanding relay descriptors
  • Understanding relay flags → maps to Guard/Exit/Stable/Fast classification
  • Exit policy parsing → maps to what traffic exits allow

Key Concepts:

Difficulty: Intermediate Time estimate: 1-2 weeks Prerequisites: HTTP, basic parsing

Real world outcome:

$ ./tor-directory --fetch --analyze

╔═══════════════════════════════════════════════════════════════╗
║              TOR NETWORK CONSENSUS ANALYZER                    ║
╚═══════════════════════════════════════════════════════════════╝

Fetching consensus from directory authorities...
  → Trying moria1.torproject.org:443... OK
  → Downloaded consensus (2.3 MB)
  → Valid from: 2024-03-15 12:00:00 UTC
  → Valid until: 2024-03-15 15:00:00 UTC
  → Fresh until: 2024-03-15 13:00:00 UTC

Parsing relay descriptors...

═══════════════════════════════════════════════════════════════
NETWORK OVERVIEW
═══════════════════════════════════════════════════════════════

Total relays: 6,847
Total bandwidth: 847.3 Gbit/s

By flag:
  Guard:     2,341 (34.2%)  ← Entry nodes for circuits
  Exit:        891 (13.0%)  ← Can route to clearnet
  Stable:    5,892 (86.0%)  ← Uptime > 7 days
  Fast:      5,234 (76.4%)  ← High bandwidth
  HSDir:     2,456 (35.9%)  ← Store hidden service descriptors
  V2Dir:     6,102 (89.1%)  ← Serve directory info

By country (top 10):
  Germany:      1,423 (20.8%)
  USA:          1,102 (16.1%)
  France:         743 (10.9%)
  Netherlands:    521 (7.6%)
  Finland:        312 (4.6%)
  ...

═══════════════════════════════════════════════════════════════
EXIT POLICY ANALYSIS
═══════════════════════════════════════════════════════════════

Exit nodes allowing port 80 (HTTP):    834 (93.6%)
Exit nodes allowing port 443 (HTTPS):  856 (96.1%)
Exit nodes allowing port 22 (SSH):     412 (46.2%)
Exit nodes allowing port 25 (SMTP):     23 (2.6%)  ← Most block email

Reduced exit policy (web-only): 234 exits
Full exit policy (most ports):  156 exits

═══════════════════════════════════════════════════════════════
SAMPLE RELAY DETAILS
═══════════════════════════════════════════════════════════════

Relay: TorExitFinland
  Fingerprint: A1B2C3D4E5F6...
  IP: 185.220.101.42
  Flags: Exit, Fast, Guard, HSDir, Running, Stable, V2Dir, Valid
  Bandwidth: 125 Mbit/s
  Exit Policy:
    accept *:80
    accept *:443
    accept *:8080
    reject *:*
  Contact: admin@torexitfinland.org
  Platform: Tor 0.4.8.10 on Linux

$ ./tor-directory --visualize --output network.html
Generated interactive network map: network.html
  → Geographic distribution
  → Bandwidth heatmap
  → Flag distribution

Implementation Hints: Fetch from https://consensus-health.torproject.org/consensus-health.html or directly from a directory authority. The consensus format is text-based with sections: network-status-version, directory signatures, and router status entries. Each router entry starts with ‘r’ (router info) followed by ‘s’ (flags), ‘w’ (bandwidth weight), ‘p’ (exit policy summary). Parse these into structured data. For visualization, use matplotlib or generate an HTML page with a map library.

Learning milestones:

  1. Fetch and parse consensus → You understand Tor’s directory system
  2. Classify relays by flags → You understand Guard/Exit/Middle roles
  3. Analyze exit policies → You understand what traffic Tor can route

Project 5: Tor Cell Protocol Implementation

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: C
  • Alternative Programming Languages: Rust, Go
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 4: Expert
  • Knowledge Area: Protocol Implementation / Binary Formats
  • Software or Tool: Protocol Implementation
  • Main Book: “TCP/IP Illustrated, Volume 1” by W. Richard Stevens

What you’ll build: An implementation of Tor’s cell format—the fixed-size 512-byte packets that carry all Tor traffic—including cell creation, parsing, and the various cell types (CREATE, RELAY, DESTROY, etc.).

Why it teaches Tor: Cells are Tor’s fundamental data unit. Understanding their fixed size (traffic analysis resistance), their types (protocol operations), and their structure (circuit IDs, commands, payloads) teaches you the protocol at the byte level.

Core challenges you’ll face:

  • Binary protocol parsing → maps to low-level data handling
  • Fixed-size cells with padding → maps to traffic analysis resistance
  • Cell type handling → maps to Tor’s command vocabulary
  • Circuit ID multiplexing → maps to multiple circuits per connection

Key Concepts:

  • Cell Format: Tor Spec - Cells - Section 3
  • Binary Protocols: “TCP/IP Illustrated, Volume 1” - Stevens
  • Network Byte Order: “Computer Systems: A Programmer’s Perspective” Chapter 11 - Bryant & O’Hallaron

Difficulty: Expert Time estimate: 2-3 weeks Prerequisites: C programming, binary data handling

Real world outcome:

$ ./tor-cells --demo

╔═══════════════════════════════════════════════════════════════╗
║              TOR CELL PROTOCOL DEMONSTRATION                   ║
╚═══════════════════════════════════════════════════════════════╝

CELL FORMAT (512 bytes total):
┌───────────────┬───────────┬─────────────────────────────────────┐
│ CircID (2/4B) │ Command   │ Payload (509/507 bytes)             │
│               │ (1 byte)  │                                     │
└───────────────┴───────────┴─────────────────────────────────────┘

Note: CircID is 2 bytes for link protocol < 4, 4 bytes otherwise

CELL COMMANDS:
  0x00: PADDING      - Keep-alive, traffic analysis resistance
  0x01: CREATE       - Create new circuit (first hop)
  0x02: CREATED      - Response to CREATE
  0x03: RELAY        - Data/control within circuit
  0x04: DESTROY      - Tear down circuit
  0x05: CREATE_FAST  - Fast circuit creation (for directory)
  0x06: CREATED_FAST - Response to CREATE_FAST
  0x07: VERSIONS     - Protocol version negotiation
  0x08: NETINFO      - Network information exchange
  0x09: RELAY_EARLY  - Extend circuit (limited use)

$ ./tor-cells --create-cell --type RELAY --circ-id 0x0001 \
    --relay-cmd DATA --data "Hello, Tor!"

Creating RELAY cell:

Header:
  Circuit ID: 0x00000001 (4 bytes, big-endian)
  Command: 0x03 (RELAY)

RELAY Payload (encrypted in real Tor):
┌─────────────┬──────────┬────────────┬────────────┬───────────┐
│ Relay Cmd   │ Recog-   │ Stream ID  │ Digest     │ Length    │
│ (1 byte)    │ nized    │ (2 bytes)(4 bytes)(2 bytes) │
│             │ (2 bytes)│            │            │           │
└─────────────┴──────────┴────────────┴────────────┴───────────┘
│ DATA payload (variable, up to 498 bytes)                     │
│ "Hello, Tor!"                                                │
└──────────────────────────────────────────────────────────────┘
│ Padding to 509 bytes total                                   │
└──────────────────────────────────────────────────────────────┘

Raw bytes (hex):
00 00 00 01 03 02 00 00 00 01 8a 3f 2c 1d 00 0b
48 65 6c 6c 6f 2c 20 54 6f 72 21 00 00 00 00 00
[... 480 more zero bytes for padding ...]

Cell size: 512 bytes (fixed!)

$ ./tor-cells --parse-cell cells.bin

Parsing cell from file...

Parsed Cell:
  Circuit ID: 1
  Command: RELAY (0x03)
  Relay Command: DATA (0x02)
  Stream ID: 1
  Data Length: 11
  Data: "Hello, Tor!"
  Padding: 487 bytes

WHY FIXED SIZE?
  All cells are exactly 512 bytes. This prevents traffic analysis:
  - Attacker can't distinguish CREATE from DATA by size
  - Can't determine message length by packet size
  - Makes timing attacks harder (uniform transmission)

Implementation Hints: In C, define a cell structure with packed attributes. Circuit ID is 4 bytes for modern protocols (2 bytes for legacy). Command byte determines payload interpretation. RELAY cells have an inner header (relay command, recognized, stream ID, digest, length) followed by data and padding. Use network byte order (big-endian) for all multi-byte fields. Implement functions: cell_create(), cell_parse(), cell_pad(), cell_serialize().

Learning milestones:

  1. Create and parse basic cells → You understand cell structure
  2. Handle RELAY cells with inner headers → You understand data encapsulation
  3. Correctly pad to 512 bytes → You understand traffic analysis resistance

Project 6: Path Selection Simulator

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Algorithms / Network Security
  • Software or Tool: Path Selection Simulator
  • Main Book: “Grokking Algorithms” by Aditya Bhargava

What you’ll build: A simulator that implements Tor’s path selection algorithm—choosing Guard, Middle, and Exit nodes based on bandwidth weights, flags, and constraints to build an optimal and secure circuit.

Why it teaches Tor: Path selection is security-critical. You’ll learn why Tor uses persistent guards (to prevent attacks), how bandwidth weights affect selection (for performance), and what constraints exist (no two nodes from same /16 network, etc.).

Core challenges you’ll face:

  • Weighted random selection → maps to bandwidth-based choice
  • Guard persistence → maps to preventing guard discovery attacks
  • Exit matching → maps to exit policies vs destination
  • Constraint enforcement → maps to family/network restrictions

Key Concepts:

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Project 4 (directory parsing), probability basics

Real world outcome:

$ ./path-selector --load-consensus consensus.txt --dest example.com:443

╔═══════════════════════════════════════════════════════════════╗
║              TOR PATH SELECTION SIMULATOR                      ║
╚═══════════════════════════════════════════════════════════════╝

Loaded 6,847 relays from consensus.

═══════════════════════════════════════════════════════════════
STEP 1: SELECT EXIT NODE
═══════════════════════════════════════════════════════════════

Destination: example.com:443 (HTTPS)
Filtering exits that allow port 443...
  Eligible exits: 856 (of 891 total exits)

Applying bandwidth weighting...
  Total exit bandwidth: 234.5 Gbit/s

Selected exit (weighted random):
  Relay: PrivacyRepublic
  Bandwidth: 850 Mbit/s (weight: 0.36%)
  Country: Netherlands
  Exit Policy: accept *:443, accept *:80, reject *:*

═══════════════════════════════════════════════════════════════
STEP 2: SELECT GUARD NODE
═══════════════════════════════════════════════════════════════

Checking for persistent guard assignment...
  Stored guards: 2 (from ~/.tor/guards)
  Guard 1: FastRelay42 (Germany) - valid, using

Note: Guards are reused for 2-3 months to prevent attacks!

Verifying guard constraints:
  ✓ Not in same /16 as exit (185.220.x.x vs 91.132.x.x)
  ✓ Not in same family as exit
  ✓ Has Guard flag
  ✓ Has Stable flag

Using guard: FastRelay42 (Germany)

═══════════════════════════════════════════════════════════════
STEP 3: SELECT MIDDLE NODE
═══════════════════════════════════════════════════════════════

Constraints:
  ✗ Cannot be guard or exit
  ✗ Cannot be in same /16 as guard or exit
  ✗ Cannot be in same family as guard or exit

Eligible middle relays: 4,892
Applying bandwidth weighting...

Selected middle:
  Relay: TorMiddleFinland
  Bandwidth: 320 Mbit/s
  Country: Finland

═══════════════════════════════════════════════════════════════
FINAL CIRCUIT
═══════════════════════════════════════════════════════════════

Path: Client → FastRelay42 → TorMiddleFinland → PrivacyRepublic → example.com

  [Client]
      │
      ▼
  [FastRelay42]        Guard   Germany    185.220.101.1
      │
      ▼
  [TorMiddleFinland]   Middle  Finland    91.132.45.67
      │
      ▼
  [PrivacyRepublic]    Exit    Netherlands 45.151.167.12
      │
      ▼
  [example.com:443]

Security properties:
  ✓ No two nodes in same country
  ✓ No two nodes in same /16 subnet
  ✓ No family relationships
  ✓ Exit allows destination port
  ✓ Using persistent guard

$ ./path-selector --simulate 1000 --stats

Running 1000 path selections...

Guard distribution (should be concentrated):
  FastRelay42:     892 (89.2%)  ← Persistent guard working!
  BackupGuard:     108 (10.8%)  ← Fallback when primary unavailable

Exit distribution (should be bandwidth-weighted):
  Top 10% exits by bandwidth: 67% of selections ✓
  Bottom 50% exits: 12% of selections

Middle distribution (should be bandwidth-weighted):
  Geographic diversity: 34 countries represented ✓

Implementation Hints: Implement weighted random selection: probability proportional to bandwidth weight. Guard selection: maintain a persistent list, only add new guards when existing ones fail. Exit selection: filter by port policy first, then weight by bandwidth. Middle selection: exclude guard and exit, exclude same /16 network, exclude same family (relays operated by same person). Constraints prevent a single operator from running your whole circuit.

Learning milestones:

  1. Select exits matching port policy → You understand exit policies
  2. Implement persistent guards → You understand guard attack prevention
  3. Enforce all constraints → You understand Tor’s security model

Project 7: Traffic Analysis Demonstration

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, C
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Security Research / Network Analysis
  • Software or Tool: Traffic Analyzer
  • Main Book: “Practical Malware Analysis” by Sikorski & Honig

What you’ll build: A tool that demonstrates traffic analysis attacks and defenses—showing how timing correlation, packet counting, and fingerprinting can deanonymize users, and how Tor’s design mitigates these attacks.

Why it teaches Tor security: Tor’s threat model includes traffic analysis. Understanding these attacks teaches you why Tor uses fixed cell sizes, why guards persist, why cover traffic exists, and what Tor can/cannot protect against.

Core challenges you’ll face:

  • Timing correlation → maps to matching entry/exit traffic
  • Website fingerprinting → maps to identifying sites by traffic patterns
  • Cell counting → maps to stream identification
  • Defense demonstration → maps to Tor’s countermeasures

Key Concepts:

Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: Basic statistics, network concepts

Real world outcome:

$ ./traffic-analysis --demo timing-correlation

╔═══════════════════════════════════════════════════════════════╗
║           TIMING CORRELATION ATTACK DEMONSTRATION              ║
╚═══════════════════════════════════════════════════════════════╝

SCENARIO: Adversary controls both Guard and Exit

Simulating traffic through Tor circuit...

TRAFFIC AT GUARD (what adversary sees entering):
  Time (ms)    Cells Received
  0            5
  100          3
  200          8
  300          2
  400          6
  Pattern: [5, 3, 8, 2, 6, ...]

TRAFFIC AT EXIT (what adversary sees exiting):
  Time (ms)    Cells Sent
  15           5      ← 15ms delay (circuit latency)
  115          3
  215          8
  315          2
  415          6
  Pattern: [5, 3, 8, 2, 6, ...]

CORRELATION ANALYSIS:
  Pearson correlation: 0.98 (very high!)
  Time offset: ~15ms (consistent latency)

ATTACK RESULT: ✗ DEANONYMIZED
  Adversary can correlate entry/exit traffic
  User's real IP linked to destination!

MITIGATION: This requires controlling BOTH Guard and Exit
  → Probability with 6800 relays, 2300 guards, 890 exits:
    P(malicious guard) × P(malicious exit) = very low
  → Using persistent guards reduces exposure over time

$ ./traffic-analysis --demo website-fingerprinting

╔═══════════════════════════════════════════════════════════════╗
║           WEBSITE FINGERPRINTING DEMONSTRATION                 ║
╚═══════════════════════════════════════════════════════════════╝

SCENARIO: Adversary observes traffic between client and guard

Training fingerprinting model on 100 websites...
  Loading traffic traces for each site...
  Extracting features:
    - Total bytes uploaded/downloaded
    - Packet timing sequences
    - Burst patterns
    - Unique packet sizes
  Training classifier... done.

Testing fingerprinting:
  Target visits: reddit.com

  Observed traffic pattern:
    Total cells: 847
    Upload cells: 123
    Download cells: 724
    Burst pattern: [15, 89, 234, 156, 78, ...]
    Timing variance: 23.4ms

  Model prediction:
    1. reddit.com (92.3% confidence) ← Correct!
    2. news.ycombinator.com (4.1%)
    3. twitter.com (1.8%)

ATTACK RESULT: ✗ Website identified without decryption!

TOR'S DEFENSES:
  1. Fixed cell size (512 bytes) - hides packet lengths
  2. Multiplexing - multiple streams per circuit add noise
  3. Padding - proposed defenses add cover traffic

REAL-WORLD LIMITATIONS:
  - Attack accuracy drops with more sites (100 → 1000 → 10000)
  - Open-world scenario (user visits any site) is much harder
  - Multi-tab browsing adds noise
  - Background traffic interferes

$ ./traffic-analysis --demo vpn-vs-tor

╔═══════════════════════════════════════════════════════════════╗
║             VPN vs TOR: TRAFFIC ANALYSIS COMPARISON            ║
╚═══════════════════════════════════════════════════════════════╝

VPN Traffic (single hop):
  Observer at VPN: Sees everything (origin IP, destination, timing)
  Observer at ISP: Sees VPN server IP, traffic volume
  Observer at destination: Sees VPN server IP

  VPN PROVIDER can correlate all traffic!
  One subpoena = complete log of your activity

TOR Traffic (3+ hops):
  Observer at Guard: Sees origin IP, encrypted blob
  Observer at Middle: Sees Guard IP, Exit IP (encrypted)
  Observer at Exit: Sees destination, no origin
  Observer at any ISP: Sees encrypted traffic, no content

  No single party has complete picture!
  Would need to compromise multiple independent nodes

CORRELATION ATTACK DIFFICULTY:
  VPN: Trivial (VPN has logs)
  Tor: Requires controlling Guard AND Exit AND timing analysis
       With 6800 relays: statistically very difficult

Implementation Hints: For timing correlation: generate synthetic traffic patterns, add latency, and compute Pearson correlation coefficient. For fingerprinting: extract features (cell counts, timing, bursts) from traffic traces, train a simple classifier (k-NN or decision tree). Compare accuracy with/without Tor’s fixed cell sizes. Show that multiplexing multiple streams provides noise. For VPN comparison, show the single-point-of-failure nature.

Learning milestones:

  1. Demonstrate timing correlation → You understand why controlling both ends is dangerous
  2. Implement basic fingerprinting → You understand website identification attacks
  3. Compare VPN vs Tor → You understand Tor’s distributed trust advantage

Project 8: Simple Exit Node Simulator

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, C
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Network Security / Proxy Systems
  • Software or Tool: Exit Node Simulator
  • Main Book: “The Linux Programming Interface” by Michael Kerrisk

What you’ll build: A simulated exit node that receives encrypted traffic from a “circuit,” decrypts the final layer, and forwards the request to the actual destination—demonstrating what an exit node can and cannot see.

Why it teaches Tor: Exit nodes are the interface between Tor and the clearnet. Understanding their role teaches you about exit policies, what exits can observe (destination + unencrypted content), and the legal/ethical considerations of running an exit.

Core challenges you’ll face:

  • Decrypting final layer → maps to exit’s unique role
  • Exit policy enforcement → maps to traffic filtering
  • Connection to destinations → maps to proxy functionality
  • Logging/privacy tradeoffs → maps to operator considerations

Key Concepts:

Difficulty: Advanced Time estimate: 2 weeks Prerequisites: Socket programming, HTTP basics

Real world outcome:

$ ./exit-simulator --policy web-only --port 9050

╔═══════════════════════════════════════════════════════════════╗
║              EXIT NODE SIMULATOR                               ║
╚═══════════════════════════════════════════════════════════════╝

Exit policy loaded: web-only
  accept *:80   (HTTP)
  accept *:443  (HTTPS)
  reject *:*    (all other ports)

Listening for circuit connections on port 9050...

[12:34:56] Received cell from circuit 0x7f3a
  Decrypting with session key...

  Destination: example.com:80
  Request type: HTTP GET

  Checking exit policy...
  ✓ Port 80 allowed

  Connecting to example.com:80...
  Forwarding request:
    GET / HTTP/1.1
    Host: example.com

  Response received (1256 bytes)
  Encrypting and sending back through circuit...

[12:34:58] Received cell from circuit 0x8a2b
  Decrypting with session key...

  Destination: 192.168.1.1:22
  Request type: SSH

  Checking exit policy...
  ✗ Port 22 NOT allowed

  Sending REJECT cell back through circuit
  Reason: Exit policy violation

═══════════════════════════════════════════════════════════════
WHAT THIS EXIT NODE CAN SEE:
═══════════════════════════════════════════════════════════════

✓ Destination IP and port
✓ HTTP requests (if not HTTPS): method, path, headers
✓ Timing of requests
✓ Approximate data volume

WHAT THIS EXIT NODE CANNOT SEE:

✗ Client's real IP (hidden by Tor circuit)
✗ Guard node identity (only sees middle node)
✗ HTTPS content (end-to-end encrypted to destination)
✗ Which other circuits belong to same user

═══════════════════════════════════════════════════════════════
EXIT OPERATOR CONSIDERATIONS:
═══════════════════════════════════════════════════════════════

⚠️  All traffic appears to come from YOUR IP
⚠️  You may receive abuse complaints
⚠️  Legal considerations vary by jurisdiction
⚠️  Reduced exit policies limit abuse (but reduce utility)

Best practices:
  • Register exit with Tor community
  • Set up reverse DNS: tor-exit.example.com
  • Maintain abuse handling process
  • Keep logs minimal (or none)

Implementation Hints: Simulate receiving encrypted cells, decrypt with the session key, extract destination and payload. Parse HTTP requests to display what the exit sees. Implement exit policy checking (port allowlists/denylists). Actually connect to destinations and relay responses. Demonstrate the difference between HTTP (exit sees content) and HTTPS (exit sees only encrypted blob to destination).

Learning milestones:

  1. Decrypt and forward to destination → You understand exit functionality
  2. Enforce exit policies → You understand traffic filtering
  3. Show HTTP vs HTTPS visibility → You understand what exits can observe

Project 9: .onion Address Generator

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: C, Rust, Go
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Cryptography / Identity
  • Software or Tool: Vanity Onion Generator
  • Main Book: “Serious Cryptography, 2nd Edition” by Jean-Philippe Aumasson

What you’ll build: A tool that generates .onion addresses by creating Ed25519 key pairs and deriving the address from the public key—including a “vanity” mode that searches for addresses starting with desired characters.

Why it teaches hidden services: .onion addresses ARE the public key (or its hash). This cryptographic binding means: (1) addresses are self-authenticating, (2) no DNS needed, (3) no central authority assigns them. Understanding this teaches you the foundation of hidden service identity.

Core challenges you’ll face:

  • Ed25519 key generation → maps to hidden service identity
  • Address derivation (base32) → maps to v3 onion format
  • Vanity address searching → maps to prefix matching at scale
  • Key security → maps to protecting hidden service identity

Key Concepts:

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Public key cryptography basics

Real world outcome:

$ ./onion-gen --generate

╔═══════════════════════════════════════════════════════════════╗
║              .ONION ADDRESS GENERATOR (v3)                     ║
╚═══════════════════════════════════════════════════════════════╝

Generating Ed25519 key pair...

Private key (KEEP SECRET!):
  ed25519:PT0ImYUuZANIEd3N8v7Jz5yE1Pd+...

Public key:
  ed25519:d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a

Computing .onion address:

  Step 1: Take public key (32 bytes)
  Step 2: Compute checksum:
          SHA3-256(".onion checksum" || pubkey || version)
          Checksum: 0x8a3f
  Step 3: Encode: base32(pubkey || checksum || version)

  Result: 2v3iqqadxmnr35bd5pfl5ujwf7whkqyl3tnnj4y2fpusyzfkb3g3mlqd.onion

Address breakdown:
  ├─ 52 chars: base32(public key)
  ├─ 2 chars: base32(checksum)
  ├─ 1 char: version (d = v3)
  └─ .onion suffix

Files saved:
  hs_ed25519_secret_key  (private key - PROTECT THIS!)
  hs_ed25519_public_key  (public key)
  hostname               (onion address)

$ ./onion-gen --vanity "mysite" --threads 8

╔═══════════════════════════════════════════════════════════════╗
║              VANITY .ONION ADDRESS SEARCH                      ║
╚═══════════════════════════════════════════════════════════════╝

Searching for addresses starting with: "mysite"
Using 8 threads...

Difficulty: 6 characters = 32^6 = 1,073,741,824 average attempts
Estimated time: ~2-10 hours at 50,000 keys/sec

Progress:
  [Thread 1] 127,453 keys generated...
  [Thread 2] 131,892 keys generated...
  ...

  Total: 1,284,567 keys checked (428,189 keys/sec)

🎉 FOUND! After 3,847,291 attempts (9 minutes)

Vanity address: mysitevk7ra4fj8a93jxpwne4c5z7yzr2f4sdftw....onion

Private key saved to: mysite_vanity.key

⚠️  SECURITY NOTE:
  Vanity addresses don't add security - they're for branding only.
  Longer prefixes = exponentially more computation time.

  5 chars: ~minutes
  6 chars: ~hours
  7 chars: ~days
  8 chars: ~weeks

$ ./onion-gen --explain-security

WHY .ONION ADDRESSES ARE SECURE:

1. SELF-AUTHENTICATING
   The address IS the public key (or its hash)
   → No DNS poisoning possible
   → No certificate authority needed
   → Cryptographic proof of identity

2. NO CENTRAL REGISTRY
   Anyone can generate addresses
   → No authority to subpoena
   → No registration records
   → Censorship resistant

3. KEY COMPROMISE = ADDRESS LOSS
   If private key is stolen:
   → Attacker can impersonate your site
   → You must generate new address
   → Like losing your domain forever

   PROTECT YOUR PRIVATE KEY!

Implementation Hints: For v3 onions: generate Ed25519 key pair, compute checksum as SHA3-256(".onion checksum" || pubkey || 0x03)[0:2], then base32-encode pubkey || checksum || 0x03. The result is 56 characters + “.onion”. For vanity search, parallelize key generation and check if base32 encoding starts with desired prefix. Use constant-time comparison for security research, though prefix matching is inherently timing-sensitive.

Learning milestones:

  1. Generate valid v3 onion addresses → You understand address derivation
  2. Verify addresses are self-authenticating → You understand the security model
  3. Implement vanity search → You understand the computational cost

Project 10: Hidden Service Descriptor Parser

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Protocol Analysis / Cryptography
  • Software or Tool: Descriptor Parser
  • Main Book: “Serious Cryptography, 2nd Edition” by Jean-Philippe Aumasson

What you’ll build: A tool that fetches and parses hidden service descriptors from the Tor network’s distributed hash table, revealing introduction points and understanding how clients discover hidden services.

Why it teaches hidden services: The descriptor is how hidden services advertise themselves. Understanding its encrypted structure, how it’s stored in the DHT, and what it reveals teaches you the discovery mechanism that makes .onion sites work.

Core challenges you’ll face:

  • DHT lookup for descriptors → maps to distributed storage
  • Descriptor decryption → maps to layered encryption
  • Introduction point parsing → maps to connection setup
  • Descriptor validation → maps to signature verification

Key Concepts:

Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: Project 9, DHT concepts

Real world outcome:

$ ./hs-descriptor --fetch duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion

╔═══════════════════════════════════════════════════════════════╗
║              HIDDEN SERVICE DESCRIPTOR ANALYSIS                ║
╚═══════════════════════════════════════════════════════════════╝

Target: duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion

Step 1: Computing HSDir responsible for this address
  Time period: 1234567 (changes every ~24 hours)
  Blinded public key: computed from onion address + time period
  HSDir indices: [a3f2..., b7c1..., d9e4...]

  Querying HSDir at 185.220.101.42...

Step 2: Fetching encrypted descriptor
  Descriptor ID: 8a3f2c1d...
  Size: 4,567 bytes
  Version: 3

Step 3: Decrypting descriptor layers
  Layer 1: Decrypted with subcredential
  Layer 2: Decrypted with client auth (if required)

═══════════════════════════════════════════════════════════════
DECRYPTED DESCRIPTOR CONTENTS
═══════════════════════════════════════════════════════════════

Descriptor created: 2024-03-15 10:00:00 UTC
Descriptor lifetime: 3 hours

Encryption type: x25519
Signature: Valid (Ed25519)

INTRODUCTION POINTS (3):
┌─────────────────────────────────────────────────────────────┐
│ Introduction Point 1                                         │
├─────────────────────────────────────────────────────────────┤
│ Relay: TorRelayNL1                                          │
│ Fingerprint: A1B2C3D4E5F6...                                │
│ Link specifiers:                                             │
│   - IPv4: 185.220.101.42:9001                               │
│   - Ed25519 identity: a1b2c3d4...                           │
│ Auth key: X25519 public key for ntor                        │
│ Enc key: Encryption key for intro cell                      │
└─────────────────────────────────────────────────────────────┘

│ Introduction Point 2                                         │
│ [Similar structure...]                                       │

│ Introduction Point 3                                         │
│ [Similar structure...]                                       │

═══════════════════════════════════════════════════════════════
HOW CONNECTION WOULD PROCEED
═══════════════════════════════════════════════════════════════

1. Client builds circuit to one of these introduction points
2. Client sends INTRODUCE1 cell (encrypted to HS public key):
   - Contains rendezvous cookie
   - Contains client's chosen rendezvous point
3. Introduction point forwards to hidden service
4. Hidden service connects to rendezvous point
5. Communication begins through rendezvous

PRIVACY ANALYSIS:
  ✓ Descriptor encrypted - HSDir can't read intro points
  ✓ Intro points don't know onion address
  ✓ Client identity hidden by Tor circuit
  ✓ Server identity hidden by Tor circuit

Implementation Hints: To fetch real descriptors, you’d need to communicate with the Tor network (complex). For learning, parse example descriptors from documentation. The v3 descriptor has two encryption layers: outer layer uses “subcredential” derived from public key and time period, inner layer optionally uses client authorization. Parse the introduction point entries to extract relay identity, link specifiers (address/port), and cryptographic keys needed for the rendezvous protocol.

Learning milestones:

  1. Parse descriptor structure → You understand hidden service advertisement
  2. Extract introduction points → You understand connection setup
  3. Understand time-based rotation → You understand descriptor freshness

Project 11: Rendezvous Protocol Simulator

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: Python
  • Alternative Programming Languages: Go, Rust
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 4: Expert
  • Knowledge Area: Distributed Systems / Cryptographic Protocols
  • Software or Tool: Rendezvous Simulator
  • Main Book: “Computer Networks, 5th Edition” by Tanenbaum

What you’ll build: A complete simulation of the Tor hidden service rendezvous protocol—demonstrating how a client and hidden service meet at a rendezvous point without either revealing their identity to the other.

Why it teaches hidden services: This is the heart of .onion functionality. Understanding introduction points, rendezvous points, and the complex dance of encrypted messages teaches you how true mutual anonymity is achieved.

Core challenges you’ll face:

  • Introduction point setup → maps to service advertisement
  • Rendezvous point establishment → maps to meeting point selection
  • INTRODUCE/RENDEZVOUS cells → maps to connection protocol
  • End-to-end encryption setup → maps to secure channel establishment

Key Concepts:

Difficulty: Expert Time estimate: 3-4 weeks Prerequisites: Projects 9, 10, understanding of Tor circuits

Real world outcome:

$ ./rendezvous-sim --full-demo

╔═══════════════════════════════════════════════════════════════╗
║         HIDDEN SERVICE RENDEZVOUS PROTOCOL SIMULATION          ║
╚═══════════════════════════════════════════════════════════════╝

═══════════════════════════════════════════════════════════════
PHASE 1: HIDDEN SERVICE SETUP
═══════════════════════════════════════════════════════════════

Hidden Service (HS) starting up...
  Onion address: abc123...xyz.onion

HS selects introduction points:
  Intro Point A: Building 3-hop circuit → TorRelay1 → TorRelay2 → IntroA
  Intro Point B: Building 3-hop circuit → TorRelay3 → TorRelay4 → IntroB
  Intro Point C: Building 3-hop circuit → TorRelay5 → TorRelay6 → IntroC

HS sends ESTABLISH_INTRO to each:
  → IntroA: "I am abc123...xyz, here's my intro key"
  → IntroB: "I am abc123...xyz, here's my intro key"
  → IntroC: "I am abc123...xyz, here's my intro key"

HS publishes descriptor to DHT:
  Descriptor contains: [IntroA, IntroB, IntroC] (encrypted)

Hidden service is now reachable at abc123...xyz.onion!

═══════════════════════════════════════════════════════════════
PHASE 2: CLIENT CONNECTS
═══════════════════════════════════════════════════════════════

Client wants to reach abc123...xyz.onion...

Step 1: Fetch descriptor from DHT
  → Querying HSDir for abc123...xyz
  → Decrypting descriptor
  → Found introduction points: [IntroA, IntroB, IntroC]

Step 2: Establish rendezvous point
  Client picks random relay as rendezvous: RendPoint
  Building circuit: Client → Guard → Middle → RendPoint

  Sending ESTABLISH_RENDEZVOUS:
    Rendezvous cookie: 0x8a3f2c1d... (random 20 bytes)

  RendPoint acknowledges: Ready to relay!

Step 3: Send INTRODUCE1 to introduction point
  Building circuit to IntroA: Client → Guard2 → Middle2 → IntroA

  INTRODUCE1 cell contains (encrypted to HS public key):
  ┌─────────────────────────────────────────────────────────┐
  │ Rendezvous point: RendPoint (identity + link specifiers)│
  │ Rendezvous cookie: 0x8a3f2c1d...                        │
  │ Client's one-time key for end-to-end encryption         │
  └─────────────────────────────────────────────────────────┘

  IntroA forwards to Hidden Service (via its circuit)

═══════════════════════════════════════════════════════════════
PHASE 3: HIDDEN SERVICE RESPONDS
═══════════════════════════════════════════════════════════════

Hidden Service receives INTRODUCE2 from IntroA:
  → Decrypting with private key
  → Found rendezvous point: RendPoint
  → Found cookie: 0x8a3f2c1d...
  → Found client's key

HS builds circuit to rendezvous point:
  HS → Guard3 → Middle3 → RendPoint

HS sends RENDEZVOUS1:
  Cookie: 0x8a3f2c1d... (proves it's the right HS)
  HS's one-time key for end-to-end encryption

RendPoint matches cookie, joins circuits!

═══════════════════════════════════════════════════════════════
PHASE 4: COMMUNICATION ESTABLISHED
═══════════════════════════════════════════════════════════════

Final circuit (6 hops total!):

[Client] ─┐
          ├─ Guard  ─ Middle ─┐
                              ├─ RendPoint ─┐
                                            ├─ Middle3 ─ Guard3 ─┐
                                                                 ├─ [Hidden Service]

End-to-end keys established:
  Client and HS derive shared secret from their one-time keys
  All traffic encrypted end-to-end (RendPoint sees only encrypted blobs)

═══════════════════════════════════════════════════════════════
PRIVACY ANALYSIS
═══════════════════════════════════════════════════════════════

What each party knows:

CLIENT:
  ✓ Onion address they connected to
  ✗ Hidden service's real IP (hidden behind 3 hops)

HIDDEN SERVICE:
  ✓ Someone connected
  ✗ Client's real IP (hidden behind 3 hops)

INTRODUCTION POINT:
  ✓ Hidden service uses this intro point
  ✗ Hidden service's IP (connects via circuit)
  ✗ Client's IP (connects via circuit)
  ✗ Rendezvous point location (encrypted in INTRODUCE)

RENDEZVOUS POINT:
  ✓ Relaying traffic between two circuits
  ✗ Who client is (just a circuit)
  ✗ Who server is (just a circuit)
  ✗ What traffic contains (end-to-end encrypted)

RESULT: TRUE MUTUAL ANONYMITY ACHIEVED!

Implementation Hints: Simulate each component as a separate process or class. The key insight: introduction points receive INTRODUCE1 cells and forward to the hidden service, but they can’t read the content (encrypted to HS public key). Rendezvous points match cookies to join circuits but never see endpoint identities. Implement the cryptographic handshake: client generates ephemeral X25519 key, HS generates ephemeral key, both derive shared secret. Show the 6-hop path: 3 from client, 3 from server.

Learning milestones:

  1. Simulate introduction point setup → You understand service advertisement
  2. Implement rendezvous establishment → You understand the meeting protocol
  3. Show end-to-end encryption → You understand complete hidden service security

Project 12: Mini Tor Network (Capstone)

  • File: TOR_ANONYMITY_NETWORKS_DEEP_DIVE_PROJECTS.md
  • Main Programming Language: C (core), Python (tooling)
  • Alternative Programming Languages: Rust, Go
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 5: Master
  • Knowledge Area: Systems Programming / Anonymity Networks
  • Software or Tool: Complete Anonymity Network
  • Main Book: “The Linux Programming Interface” by Michael Kerrisk

What you’ll build: A complete mini-Tor network from scratch: directory authority, relay nodes (guard, middle, exit), circuit building, onion encryption, and basic hidden service support—all without using any Tor code.

Why this is the ultimate project: This forces you to understand every component of Tor and how they fit together. You’ll face real challenges: key management, circuit timing, cell handling, and the subtle details that make anonymity work.

Core challenges you’ll face:

  • Directory authority implementation → maps to network state management
  • Relay node with all roles → maps to Guard/Middle/Exit functionality
  • Circuit building protocol → maps to CREATE/EXTEND handling
  • Onion encryption/decryption → maps to layered crypto in practice
  • Hidden service basics → maps to introduction/rendezvous
  • Cell multiplexing → maps to multiple circuits per connection

Key Concepts:

Difficulty: Master Time estimate: 2-3 months Prerequisites: All previous projects, strong C/systems programming

Real world outcome:

# Terminal 1: Start directory authority
$ ./mini-tor directory --port 7000
╔═══════════════════════════════════════════════════════════════╗
║              MINI-TOR DIRECTORY AUTHORITY                      ║
╚═══════════════════════════════════════════════════════════════╝
Listening on port 7000
Waiting for relay registrations...

# Terminal 2: Start relay A (Guard/Middle)
$ ./mini-tor relay --dir localhost:7000 --port 7001 --flags guard,middle
Registered with directory authority
Fingerprint: A1B2C3D4...
Flags: Guard, Middle
Listening for circuits on port 7001

# Terminal 3: Start relay B (Middle)
$ ./mini-tor relay --dir localhost:7000 --port 7002 --flags middle
Registered with directory authority
Fingerprint: E5F6G7H8...

# Terminal 4: Start relay C (Exit)
$ ./mini-tor relay --dir localhost:7000 --port 7003 --flags exit --policy "accept *:80,443"
Registered with directory authority
Fingerprint: I9J0K1L2...
Exit policy: accept *:80, accept *:443, reject *:*

# Terminal 5: Client connects
$ ./mini-tor client --dir localhost:7000

╔═══════════════════════════════════════════════════════════════╗
║              MINI-TOR CLIENT                                   ║
╚═══════════════════════════════════════════════════════════════╝

Fetching consensus from directory...
  Known relays: 3
  Guards: 1, Exits: 1

Building circuit...
  Step 1: Connect to guard (Relay A, port 7001)
    → CREATE cell sent
    ← CREATED cell received
    → Session key established: k_A

  Step 2: Extend to middle (Relay B)
    → EXTEND cell through A
    ← EXTENDED cell received
    → Session key established: k_B

  Step 3: Extend to exit (Relay C)
    → EXTEND cell through A→B
    ← EXTENDED cell received
    → Session key established: k_C

Circuit established: Client → A → B → C → Internet
Circuit ID: 0x0001

mini-tor> fetch http://example.com/
Encrypting request...
  Layer 3: Encrypt("GET / HTTP/1.1...", k_C)
  Layer 2: Encrypt([layer3], k_B)
  Layer 1: Encrypt([layer2], k_A)

Sending through circuit...

[Relay A] Received cell, decrypted, forwarding to B
[Relay B] Received cell, decrypted, forwarding to C
[Relay C] Received cell, decrypted, destination: example.com:80
[Relay C] Fetching from example.com...
[Relay C] Response received, encrypting, sending back

Response received (1.2 KB):
<!doctype html>
<html>
<head>
    <title>Example Domain</title>
...

mini-tor> .onion-setup
Setting up hidden service...
  Generated onion address: xyz123...abc.onion
  Establishing introduction points...
    → IntroPoint at Relay B: ESTABLISHED
  Publishing descriptor to directory...

Hidden service running at: xyz123...abc.onion
  Serving local port 8080

# Another client connects to .onion
mini-tor2> fetch xyz123...abc.onion
Fetching descriptor from directory...
Connecting to introduction point (Relay B)...
Establishing rendezvous at Relay A...
Sending INTRODUCE1...
Waiting for RENDEZVOUS1...
Connected to hidden service!

Response from xyz123...abc.onion:
Hello from hidden service!

═══════════════════════════════════════════════════════════════
MINI-TOR NETWORK STATISTICS
═══════════════════════════════════════════════════════════════

Active relays: 3
Active circuits: 4
Active hidden services: 1
Cells transmitted: 1,247
Bytes relayed: 637 KB

Anonymity verification:
  ✓ No relay knows both client IP and destination
  ✓ Hidden service IP never revealed
  ✓ All traffic encrypted in layers

Implementation Hints: Start with the directory authority: accept relay registrations, publish consensus. Then implement relays: handle CREATE/CREATED for first hop, EXTEND/EXTENDED for extensions, RELAY cells for data. Use fixed 512-byte cells. Implement onion encryption: each relay has a session key, client encrypts in layers. For hidden services, implement simplified introduction points and rendezvous (the rendezvous simulator helps here). Use separate threads for each circuit. This project integrates everything from all previous projects.

Learning milestones:

  1. Directory + 3 relays communicating → You understand network bootstrap
  2. Client builds circuit and fetches HTTP → You understand onion routing
  3. Hidden service works end-to-end → You’ve built a complete anonymity network

Project Comparison Table

Project Difficulty Time Depth of Understanding Fun Factor Business Value
1. Layered Encryption Simulator Intermediate 1 week ★★★☆☆ ★★★★☆ Resume Gold
2. DH Key Exchange Demo Advanced 2 weeks ★★★★☆ ★★★☆☆ Resume Gold
3. Onion Network Simulator Advanced 2-3 weeks ★★★★☆ ★★★★★ Resume Gold
4. Directory Parser Intermediate 1-2 weeks ★★★☆☆ ★★★☆☆ Micro-SaaS
5. Cell Protocol Implementation Expert 2-3 weeks ★★★★★ ★★★★☆ Resume Gold
6. Path Selection Simulator Advanced 2 weeks ★★★★☆ ★★★☆☆ Resume Gold
7. Traffic Analysis Demo Advanced 2-3 weeks ★★★★☆ ★★★★★ Resume Gold
8. Exit Node Simulator Advanced 2 weeks ★★★☆☆ ★★★★☆ Resume Gold
9. Onion Address Generator Advanced 1-2 weeks ★★★☆☆ ★★★★★ Micro-SaaS
10. HS Descriptor Parser Advanced 2-3 weeks ★★★★☆ ★★★☆☆ Micro-SaaS
11. Rendezvous Simulator Expert 3-4 weeks ★★★★★ ★★★★★ Resume Gold
12. Mini Tor Network Master 2-3 months ★★★★★ ★★★★★ Open Core

If you want to understand “Why Tor is different from VPN”:

  1. Project 1 (Layered Encryption) - See the fundamental difference: one layer vs many
  2. Project 7 (Traffic Analysis Demo) - See what Tor protects that VPN doesn’t
  3. Project 3 (Onion Network Simulator) - See distributed trust in action

If you want to understand hidden services (.onion):

  1. Project 9 (Onion Address Generator) - Understand address = public key
  2. Project 10 (Descriptor Parser) - Understand how services advertise
  3. Project 11 (Rendezvous Simulator) - Understand mutual anonymity

If you want the deepest technical understanding:

  1. Work through Projects 1 → 2 → 3 (cryptography foundations)
  2. Then Projects 4 → 5 → 6 (protocol details)
  3. Then Projects 7 → 8 (security analysis)
  4. Then Projects 9 → 10 → 11 (hidden services)
  5. Finally, Project 12 (Mini Tor Network) - Build it all from scratch

If you’re interested in security research:

  1. Project 7 (Traffic Analysis) - Understand attack vectors
  2. Project 6 (Path Selection) - Understand guard discovery attacks
  3. Project 8 (Exit Simulator) - Understand exit risks
  4. Then read the academic papers on Tor attacks

Key Resources Summary

Official Specifications

Academic Papers

Books

  • “Serious Cryptography, 2nd Edition” by Jean-Philippe Aumasson - Cryptography foundations
  • “Computer Networks, 5th Edition” by Tanenbaum - Networking fundamentals
  • “The Linux Programming Interface” by Michael Kerrisk - Systems programming
  • “Practical Malware Analysis” by Sikorski & Honig - Security analysis techniques

Community Resources


Summary

# Project Main Language
1 Layered Encryption Simulator Python
2 Diffie-Hellman Key Exchange Demo Python
3 Onion Routing Network Simulator Python
4 Tor Directory Parser & Network Visualizer Python
5 Tor Cell Protocol Implementation C
6 Path Selection Simulator Python
7 Traffic Analysis Demonstration Python
8 Simple Exit Node Simulator Python
9 .onion Address Generator Python
10 Hidden Service Descriptor Parser Python
11 Rendezvous Protocol Simulator Python
12 Mini Tor Network (Capstone) C + Python

The Core Insight

After completing these projects, you’ll understand:

VPN: “I trust one company with all my traffic, and they give me a different IP address.”

Tor: “I trust mathematics. No single party—not even the Tor Project—can deanonymize me because:

  • Guard knows my IP but not my destination
  • Middle knows neither
  • Exit knows my destination but not my IP
  • The cryptography ensures this mathematically”

Hidden Services: “Not only is my identity hidden, but the server’s identity is too. We meet through an encrypted rendezvous that neither controls. This is what makes the ‘dark web’ possible—services that literally cannot be located or shut down by IP address.”

By building these projects, you’ll transform from someone who “uses Tor” to someone who truly understands how distributed anonymity networks achieve what no centralized service ever could.


A Note on Ethics

The same technology that protects journalists and activists also enables illegal markets. Understanding Tor deeply comes with responsibility. Use this knowledge to:

  • Build privacy-preserving systems
  • Contribute to Tor’s security research
  • Help people in oppressive regimes communicate safely
  • Understand the limitations of anonymity systems

Never use it to harm others.