A Python port of the Invisible Internet Project (I2P)
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>