A Python port of the Invisible Internet Project (I2P)
at main 288 lines 14 kB view raw
1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<meta charset="UTF-8"> 5<meta name="viewport" content="width=device-width, initial-scale=1.0"> 6<title>Porting I2P from Java to Python: A Build Log</title> 7<link rel="preconnect" href="https://fonts.googleapis.com"> 8<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Space+Mono:wght@400;700&family=Syne:wght@400;600;700;800&display=swap" rel="stylesheet"> 9<style> 10 *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } 11 :root { 12 --navy: #06091a; --navy2: #0c1230; --navy3: #111a3e; 13 --red: #ff2b4a; --mint: #00e5a0; --cyan: #00c8ff; 14 --gray: #8a95b0; --light: #c8d0e8; --white: #eef1fb; 15 --mono: 'Space Mono', monospace; 16 --display: 'Bebas Neue', sans-serif; 17 --body: 'Syne', sans-serif; 18 } 19 html { scroll-behavior: smooth; } 20 body { background: var(--navy); color: var(--white); font-family: var(--body); font-size: 16px; line-height: 1.6; } 21 22 nav { 23 position: fixed; top: 0; left: 0; right: 0; z-index: 100; 24 display: flex; align-items: center; justify-content: space-between; 25 padding: 1.25rem 2.5rem; 26 background: linear-gradient(to bottom, rgba(6,9,26,0.95), transparent); 27 backdrop-filter: blur(2px); 28 } 29 .nav-logo { font-family: var(--mono); font-size: 13px; color: var(--mint); letter-spacing: 0.08em; text-decoration: none; } 30 .nav-links { display: flex; gap: 2rem; list-style: none; } 31 .nav-links a { font-family: var(--mono); font-size: 12px; color: var(--gray); text-decoration: none; letter-spacing: 0.05em; transition: color 0.2s; } 32 .nav-links a:hover { color: var(--white); } 33 .nav-cta { font-family: var(--mono); font-size: 12px; color: var(--navy); background: var(--mint); padding: 0.5rem 1.25rem; text-decoration: none; letter-spacing: 0.05em; } 34 35 .article { max-width: 720px; margin: 0 auto; padding: 8rem 2rem 5rem; } 36 .article-tag { font-family: var(--mono); font-size: 11px; color: var(--red); letter-spacing: 0.2em; text-transform: uppercase; margin-bottom: 1.5rem; } 37 .article h1 { font-family: var(--display); font-size: clamp(48px, 8vw, 80px); line-height: 0.95; margin-bottom: 1.5rem; } 38 .article h1 .mint { color: var(--mint); } 39 .article .lede { font-size: 18px; color: var(--light); line-height: 1.7; margin-bottom: 3rem; border-left: 2px solid var(--mint); padding-left: 1.25rem; } 40 .article h2 { font-family: var(--display); font-size: 40px; color: var(--white); margin: 3.5rem 0 1rem; letter-spacing: 0.02em; } 41 .article h2 .accent { color: var(--red); } 42 .article h2 .mint { color: var(--mint); } 43 .article p { font-size: 15px; color: var(--light); line-height: 1.8; margin-bottom: 1.25rem; } 44 .article p strong { color: var(--white); font-weight: 700; } 45 .article p code { font-family: var(--mono); font-size: 13px; color: var(--cyan); background: rgba(0,200,255,0.08); padding: 0.1em 0.4em; } 46 .article a { color: var(--mint); text-decoration: none; border-bottom: 1px solid rgba(0,229,160,0.3); transition: border-color 0.2s; } 47 .article a:hover { border-color: var(--mint); } 48 49 .stats-row { 50 display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); 51 gap: 2px; margin: 2.5rem 0; background: var(--navy2); border: 1px solid rgba(0,229,160,0.15); padding: 0; 52 } 53 .stat-cell { padding: 1.5rem; background: var(--navy); text-align: center; } 54 .stat-cell .num { font-family: var(--display); font-size: 40px; color: var(--mint); display: block; } 55 .stat-cell .label { font-family: var(--mono); font-size: 10px; color: var(--gray); letter-spacing: 0.1em; margin-top: 0.25rem; display: block; } 56 57 .credit-block { 58 background: var(--navy2); border: 1px solid rgba(255,255,255,0.06); 59 padding: 2rem; margin: 2rem 0; 60 } 61 .credit-block .name { font-family: var(--mono); font-size: 13px; color: var(--mint); letter-spacing: 0.1em; margin-bottom: 0.75rem; } 62 .credit-block p { margin-bottom: 0; } 63 64 footer { 65 padding: 2.5rem; border-top: 1px solid rgba(255,255,255,0.06); 66 display: flex; align-items: center; justify-content: space-between; 67 } 68 footer .footer-left { font-family: var(--mono); font-size: 11px; color: var(--gray); letter-spacing: 0.08em; } 69 footer .footer-right { display: flex; gap: 1.5rem; } 70 footer a { font-family: var(--mono); font-size: 11px; color: var(--gray); text-decoration: none; letter-spacing: 0.08em; transition: color 0.2s; } 71 footer a:hover { color: var(--white); } 72 73 @media (max-width: 768px) { 74 nav { padding: 1rem 1.25rem; } 75 .nav-links { display: none; } 76 .article { padding: 6rem 1.25rem 3rem; } 77 .stats-row { grid-template-columns: 1fr 1fr; } 78 } 79</style> 80</head> 81<body> 82 83<nav> 84 <a href="index.html" class="nav-logo">i2p // python</a> 85 <ul class="nav-links"> 86 <li><a href="index.html#attack">The Attack</a></li> 87 <li><a href="index.html#compare">Why I2P</a></li> 88 <li><a href="blog.html">The Port</a></li> 89 <li><a href="the-fix.html">The Fix</a></li> 90 </ul> 91 <a href="https://github.com/Bimo-Studio/i2p-python" class="nav-cta">VIEW ON GITHUB</a> 92</nav> 93 94<article class="article"> 95 <div class="article-tag">BUILD LOG</div> 96 <h1>Porting I2P from Java to <span class="mint">Python</span></h1> 97 98 <p class="lede"> 99 The Invisible Internet Project has been running for over twenty years. Its Java 100 implementation is one of the most battle-tested privacy systems in existence. 101 This is the story of porting it to Python — and why. 102 </p> 103 104 <!-- WHY --> 105 <h2>Why <span class="accent">Port</span> I2P?</h2> 106 <p> 107 Ethereum validators are broadcasting their home IP addresses to anyone who asks. 108 Researchers proved it — four nodes, 72 hours, 15% of all validators deanonymized. 109 The fix is I2P: give nodes private addresses that can't be traced back to physical 110 locations. 111 </p> 112 <p> 113 But integrating I2P into Ethereum clients means those clients need an I2P stack. 114 The Java implementation is excellent — but Ethereum clients are written in Go, Rust, 115 C#, and Python. Asking each team to embed a JVM is a non-starter. 116 </p> 117 <p> 118 A native Python implementation unlocks I2P for the entire Python ecosystem: not 119 just Ethereum, but any application that needs anonymous networking. Libraries, 120 services, CLI tools — all in a language that 70% of developers already know. 121 </p> 122 123 <!-- ORIGINAL TEAM --> 124 <h2>The Original I2P <span class="mint">Team</span></h2> 125 <p> 126 <strong>This port exists because of the people who built I2P in the first place.</strong> 127 </p> 128 <p> 129 jrandom designed the original architecture and wrote much of the initial codebase. 130 zzz has been the project's backbone for over a decade — maintaining the router, 131 reviewing patches, keeping the network running through every challenge. str4d 132 contributed critical cryptographic work and protocol improvements. 133 </p> 134 <p> 135 The I2P community has maintained this infrastructure for twenty years. They did it 136 without venture funding, without a token sale, without hype cycles. The Java I2P 137 core — i2p.jar, router.jar, SAM, streaming — is released into the <strong>public 138 domain</strong>. That's an extraordinary gift. Every line of this Python port exists 139 because they wrote the specification and the reference implementation first. 140 </p> 141 <p> 142 We owe them everything. This is a port built on their shoulders. 143 </p> 144 145 <!-- DOLLSPACE-GAY --> 146 <h2><span class="mint">dollspace-gay</span></h2> 147 <p> 148 dollspace-gay's contributions to the I2P ecosystem deserve specific recognition. 149 Their work on I2P tooling, community engagement, and documentation has helped make 150 I2P more accessible to developers who aren't steeped in the project's two-decade 151 history. The kind of bridge-building work that makes ecosystems thrive. 152 </p> 153 154 <!-- CLAUDE --> 155 <h2><span class="cyan" style="color: var(--cyan);">Claude</span></h2> 156 <p> 157 Let's be direct about this: significant portions of i2p-python were generated by 158 <strong>Claude</strong>, Anthropic's AI assistant. Not as a novelty. As a core contributor. 159 </p> 160 <p> 161 Claude wrote crypto implementations that pass byte-identical parity tests against 162 Java reference vectors. It generated security audits that found real timing-attack 163 vulnerabilities and nonce overflow bugs. It produced 3,240+ tests. It built the 164 cross-platform packaging infrastructure — deb, rpm, Windows exe — from scratch. 165 </p> 166 <p> 167 The collaboration model was human direction + AI implementation. A human decided 168 <em>what</em> to build and <em>why</em>. Claude figured out <em>how</em> and did 169 the work. This is what made a port of this scale feasible for a small team — the 170 kind of project that would normally require a dozen engineers and a year of work. 171 </p> 172 173 <!-- IRONCARAPACE --> 174 <h2>The <span class="mint">bimo.studio</span> System</h2> 175 <p> 176 i2p-python wasn't built by hand in a text editor. It was built by 177 <strong>bimo.studio</strong> — an autonomous development platform that orchestrates 178 the entire software delivery lifecycle. 179 </p> 180 <p> 181 At the center is <strong>Chainlink</strong>, a VDD (Verification-Driven Development) 182 pipeline that enforces a strict progression: specification, tests, implementation, 183 gates. No code ships without passing automated verification. No tier advances without 184 its prerequisites proven. 185 </p> 186 <p> 187 The I2P port was organized into 20 tiers of dependencies — from foundational 188 utilities (Tier 0) through crypto primitives (Tiers 1-5), data structures (Tiers 6-9), 189 transports (Tiers 12-14), up to the full router (Tier 17). Each tier's packages had 190 to pass parity tests against the Java reference before the next tier could begin. 191 </p> 192 193 <!-- POLYPORT --> 194 <h2><span class="mint">PolyPort</span>: The Polyglot Engine</h2> 195 <p> 196 PolyPort is the porting subsystem that made the Java-to-Python translation tractable. 197 It's a general-purpose tool — not specific to I2P or to Java/Python — designed to port 198 any codebase between any language pair. 199 </p> 200 <p> 201 The Java I2P source was ingested into a <strong>pgvector</strong> semantic database: 202 40,340 code chunks from 1,920 files across 179 packages. PolyPort queries this 203 database to find the relevant Java source for each Python module being implemented, 204 generates test vectors from the Java reference, scaffolds the Python package structure, 205 and orchestrates the TDD cycle. 206 </p> 207 <p> 208 This isn't a transpiler. It doesn't do line-by-line translation. It understands the 209 <em>intent</em> of the Java code and produces idiomatic Python that achieves the same 210 result — verified by byte-identical parity tests. 211 </p> 212 213 <!-- BY THE NUMBERS --> 214 <h2>By The <span class="accent">Numbers</span></h2> 215 216 <div class="stats-row"> 217 <div class="stat-cell"><span class="num">15</span><span class="label">PACKAGES</span></div> 218 <div class="stat-cell"><span class="num">34</span><span class="label">REPOS</span></div> 219 <div class="stat-cell"><span class="num">3,240+</span><span class="label">TESTS</span></div> 220 <div class="stat-cell"><span class="num">14</span><span class="label">CRYPTO PRIMITIVES</span></div> 221 <div class="stat-cell"><span class="num">40k</span><span class="label">JAVA CHUNKS INGESTED</span></div> 222 <div class="stat-cell"><span class="num">2</span><span class="label">TRANSPORTS (NTCP2+SSU2)</span></div> 223 </div> 224 225 <p> 226 Every crypto primitive — AES-256-CBC, ChaCha20-Poly1305, Ed25519, X25519, ElGamal, 227 DSA, HKDF, HMAC-SHA256, SipHash, ML-KEM (post-quantum) — passes parity tests against 228 Java reference vectors. The NTCP2 transport completes Noise XK handshakes with live 229 Java I2P peers. The SAM v3 bridge implements the full session/stream/datagram protocol. 230 </p> 231 232 <!-- WHAT'S NEXT --> 233 <h2>What's <span class="mint">Next</span></h2> 234 <p> 235 <strong>Ethereum ENR integration.</strong> An EIP draft proposes adding an <code>"i2p"</code> 236 key to Ethereum Node Records — 32 bytes that replace your cleartext IP with an I2P 237 destination hash. i2p-python provides the stack that makes this work. 238 </p> 239 <p> 240 <strong>Live network testing.</strong> Extended participation on the I2P network to 241 validate tunnel building, relay performance, and interoperability at scale. 242 </p> 243 <p> 244 <strong>Performance benchmarking.</strong> Profiling against the Java implementation 245 to identify and close performance gaps in the Python port. 246 </p> 247 <p> 248 <strong>Post-quantum readiness.</strong> ML-KEM (Kyber) is already implemented. As the 249 I2P protocol evolves its post-quantum migration, this implementation will track it. 250 </p> 251 252 <!-- CREDITS --> 253 <h2><span class="mint">Credits</span></h2> 254 255 <div class="credit-block"> 256 <div class="name">THE I2P PROJECT</div> 257 <p>jrandom, zzz, str4d, and the entire I2P community. Twenty years of privacy infrastructure, released to the public domain.</p> 258 </div> 259 260 <div class="credit-block"> 261 <div class="name">DOLLSPACE-GAY</div> 262 <p>For contributions to the I2P ecosystem and community that made this work richer.</p> 263 </div> 264 265 <div class="credit-block"> 266 <div class="name">CLAUDE (ANTHROPIC)</div> 267 <p>AI-generated code, tests, security audits, and packaging. A genuine collaborator, not a gimmick.</p> 268 </div> 269 270 <div class="credit-block"> 271 <div class="name" style="color: var(--white);">BIMO.STUDIO</div> 272 <p>This project was driven by <a href="https://bimo.studio" style="color: var(--mint);">bimo.studio</a>. Not a corporation. A studio that believes privacy infrastructure should exist, and that the best way to make it exist is to build it.</p> 273 </div> 274 275</article> 276 277<footer> 278 <div class="footer-left"> 279 i2p // python — MIT LICENSE — A <a href="https://bimo.studio" style="color: var(--mint);">bimo.studio</a> PROJECT 280 </div> 281 <div class="footer-right"> 282 <a href="index.html">HOME</a> 283 <a href="https://github.com/Bimo-Studio/i2p-python">GITHUB</a> 284 </div> 285</footer> 286 287</body> 288</html>