PageSourceSearch

https://hp2p.net/

html hp2p.net collected 2026-09-28 07:08:50 UTC 16,438 bytes, 450 lines download raw bytes

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>HermesP2P — Safe. Secure. Sovereign.</title>
7    <meta name="description" content="Decentralized, ephemeral peer-to-peer messaging. No servers, no persistence, no compromise.">
8    <link rel="icon" type="image/pdf" href="/static/images/favicon.pdf">
9    <link href="/static/css/style.css" rel="stylesheet">
10    <style>
11        * { margin: 0; padding: 0; box-sizing: border-box; }
12        body {
13            font-family: Arial, Helvetica, sans-serif;
14            background: #ffffff;
15            color: #333;
16            line-height: 1.6;
17        }
18        a { color: #000033; text-decoration: none; }
19        a:hover { text-decoration: underline; }
20
21        /* Hero */
22        .hero {
23            text-align: center;
24            padding: 48px 24px 40px;
25            max-width: 800px;
26            margin: 0 auto;
27        }
28        .hero img { height: 120px; margin-bottom: 16px; }
29        .hero h1 {
30            font-size: 2.4rem;
31            color: #000033;
32            letter-spacing: -0.02em;
33            margin-bottom: 4px;
34        }
35        .hero .tagline {
36            font-size: 1.2rem;
37            font-style: italic;
38            color: #6c757d;
39            margin-bottom: 16px;
40        }
41        .hero .subtitle {
42            font-size: 1.05rem;
43            color: #555;
44            max-width: 600px;
45            margin: 0 auto 28px;
46        }
47        .cta-group {
48            display: flex;
49            gap: 12px;
50            justify-content: center;
51            flex-wrap: wrap;
52            margin-bottom: 8px;
53        }
54        .btn {
55            display: inline-block;
56            padding: 10px 24px;
57            border-radius: 6px;
58            font-weight: 600;
59            font-size: 0.95rem;
60            cursor: pointer;
61            border: none;
62            transition: background 0.15s ease;
63        }
64        .btn-primary {
65            background: #000033;
66            color: #fff !important;
67        }
68        .btn-primary:hover {
69            background: #000055;
70            text-decoration: none;
71        }
72        .btn-secondary {
73            background: #e9ecef;
74            color: #000033 !important;
75            border: 1px solid #ced4da;
76        }
77        .btn-secondary:hover {
78            background: #dee2e6;
79            text-decoration: none;
80        }
81
82        /* Sections */
83        .section {
84            max-width: 800px;
85            margin: 0 auto;
86            padding: 0 24px 48px;
87        }
88        .section h2 {
89            font-size: 1.5rem;
90            color: #000033;
91            margin-bottom: 16px;
92            padding-top: 32px;
93            border-top: 1px solid #e9ecef;
94        }
95        .section h2:first-child { border-top: none; padding-top: 0; }
96        .section p {
97            color: #555;
98            font-size: 1rem;
99            margin-bottom: 12px;
100        }
101
102        /* Feature grid */
103        .feature-grid {
104            display: grid;
105            grid-template-columns: repeat(3, 1fr);
106            gap: 20px;
107            margin: 20px 0;
108        }
109        .feature-card {
110            background: #f8f9fa;
111            border: 1px solid #e9ecef;
112            border-radius: 8px;
113            padding: 20px;
114        }
115        .feature-card h3 {
116            font-size: 1rem;
117            color: #000033;
118            margin-bottom: 6px;
119        }
120        .feature-card p {
121            font-size: 0.9rem;
122            color: #6c757d;
123            margin: 0;
124        }
125
126        /* Protocol features */
127        .protocol-grid {
128            display: grid;
129            grid-template-columns: repeat(2, 1fr);
130            gap: 16px;
131            margin: 20px 0;
132        }
133        .protocol-item {
134            display: flex;
135            gap: 12px;
136            align-items: flex-start;
137        }
138        .protocol-num {
139            flex-shrink: 0;
140            width: 32px;
141            height: 32px;
142            border-radius: 50%;
143            background: #000033;
144            color: #fff;
145            display: flex;
146            align-items: center;
147            justify-content: center;
148            font-weight: 700;
149            font-size: 0.85rem;
150        }
151        .protocol-item h4 {
152            font-size: 0.95rem;
153            color: #000033;
154            margin-bottom: 2px;
155        }
156        .protocol-item p {
157            font-size: 0.9rem;
158            color: #6c757d;
159            margin: 0;
160        }
161
162        /* Auth box */
163        .auth-box {
164            background: #f8f9fa;
165            border: 1px solid #e9ecef;
166            border-radius: 8px;
167            padding: 24px;
168            margin: 20px 0;
169            font-family: 'SF Mono', 'Fira Code', Menlo, Consolas, monospace;
170            font-size: 0.85rem;
171            line-height: 1.8;
172            color: #6c757d;
173        }
174        .auth-box .label { color: #000033; font-weight: 600; }
175        .auth-box .arrow { color: #000033; }
176
177        /* Upload status */
178        .alert { padding: 12px 16px; border-radius: 6px; margin-top: 12px; font-size: 0.95rem; }
179        .alert-info { background: #e7f3ff;
179 color: #0c5460; }
180        .alert-success { background: #d4edda; color: #155724; }
181        .alert-danger { background: #f8d7da; color: #721c24; }
182        .d-none { display: none; }
183
184        /* Book */
185        .book-box {
186            background: #f8f9fa;
187            border: 1px solid #e9ecef;
188            border-radius: 8px;
189            padding: 28px;
190            text-align: center;
191            margin: 20px 0;
192        }
193        .book-box h3 {
194            font-size: 1.1rem;
195            color: #000033;
196            margin-bottom: 8px;
197        }
198        .book-box p {
199            color: #6c757d;
200            font-size: 0.95rem;
201            max-width: 500px;
202            margin: 0 auto 16px;
203        }
204
205        /* Footer */
206        footer {
207            text-align: center;
208            padding: 24px;
209            color: #6c757d;
210            font-size: 0.85rem;
211            border-top: 1px solid #e9ecef;
212            max-width: 800px;
213            margin: 0 auto;
214        }
215
216        @media (max-width: 768px) {
217            .hero h1 { font-size: 1.8rem; }
218            .feature-grid { grid-template-columns: 1fr; }
219            .protocol-grid { grid-template-columns: 1fr; }
220            .support-grid { grid-template-columns: 1fr; }
221        }
222    </style>
223</head>
224<body>
225
226<section class="hero">
227    <img src="/static/images/hermesp2p.png" alt="HermesP2P Logo">
228    <h1>HermesP2P</h1>
229    <p class="tagline">Safe. Secure. Sovereign.</p>
230    <p class="subtitle">
231        Decentralized, ephemeral peer-to-peer messaging.
232        No servers store your messages. No accounts to breach.
233        Your config file is your identity &mdash; upload it and you're you.
234    </p>
235    <div class="cta-group">
236        <input type="file" id="configFile" accept=".json" style="display:none">
237        <button onclick="document.getElementById('configFile').click()" class="btn btn-secondary">Upload Config</button>
238        <a href="/client" class="btn btn-primary">New Identity</a>
239    </div>
240    <div id="uploadStatus" class="alert d-none"></div>
241</section>
242
243<div class="section">
244    <h2>Three Principles</h2>
245    <div class="feature-grid">
246        <div class="feature-card">
247            <h3>Ephemeral</h3>
248            <p>Messages are transient. They exist in memory during transit and are never persisted. No server stores your history. No database to subpoena.</p>
249        </div>
250        <div class="feature-card">
251            <h3>Decentralized</h3>
252            <p>No central servers, no authority, no single point of failure. Every node contributes to resilience. The network self-organizes.</p>
253        </div>
254        <div class="feature-card">
255            <h3>Sovereign</h3>
256            <p>Your Ed25519 keypair is your identity. Private keys never leave your device. No passwords, no accounts, no third-party authentication.</p>
257        </div>
258    </div>
259</div>
260
261<div class="section">
262    <h2>Stateless Authentication</h2>
263    <p>
264        There are no accounts. No passwords. No sessions stored on a server.
265        <strong>Your configuration file IS your identity.</strong>
266        It contains your keypair, your channels, your contacts' public keys, and your peer list.
267        Upload it to any node and you're authenticated. Download it when you leave. The node forgets you existed.
268    </p>
269    <div class="auth-box">
270        <div><span class="label">Config File</span></div>
271        <div>&nbsp; <span class="arrow">+--</span> <span class="label">keypair</span>: Ed25519 public/private keys</div>
272        <div>&nbsp; <span class="arrow">+--</span> <span class="label">channels</span>: subscribed public &amp; private topics</div>
273        <div>&nbsp; <span class="arrow">+--</span> <span class="label">friends</span>: contacts' public keys</div>
274        <div>&nbsp; <span class="arrow">+--</span> <span class="label">peers</span>: known network nodes</div>
275        <div>&nbsp;</div>
276        <div><span class="arrow">&gt;</span> Upload to any node = authenticated</div>
277        <div><span class="arrow">&gt;</span> Download when done = node forgets you</div>
278        <div><span class="arrow">&gt;</span> No server state. No breach surface.</div>
279    </div>
280</div>
281
282<div class="section">
283    <h2>Protocol Features</h2>
284    <div class="protocol-grid">
285        <div class="protocol-item">
286            <div class="protocol-num">1</div>
287            <div>
288                <h4>Ed25519 Signatures</h4>
289                <p>Every message is signed. Every signature is verified at every hop. No impersonation possible.</p>
290            </div>
291        </div>
292        <div class="protocol-item">
293            <div class="protocol-num">2</div>
294            <div>
295                <h4>Fixed-Size Padding</h4>
296                <p>Messages are padded to fixed sizes (1KB/4KB/16KB/64KB) to prevent traffic analysis. Ob
296servers can't distinguish message types by size.</p>
297            </div>
298        </div>
299        <div class="protocol-item">
300            <div class="protocol-num">3</div>
301            <div>
302                <h4>TTL Hop Control</h4>
303                <p>Time-to-live counters control message propagation depth. Messages spread through the network efficiently without flooding.</p>
304            </div>
305        </div>
306        <div class="protocol-item">
307            <div class="protocol-num">4</div>
308            <div>
309                <h4>Peer Discovery</h4>
310                <p>Nodes discover peers and build diverse connection graphs automatically. The network adapts and self-heals.</p>
311            </div>
312        </div>
313        <div class="protocol-item">
314            <div class="protocol-num">5</div>
315            <div>
316                <h4>Pseudonyms</h4>
317                <p>Channel-specific pseudonyms let you participate in public channels without revealing your global identity.</p>
318            </div>
319        </div>
320        <div class="protocol-item">
321            <div class="protocol-num">6</div>
322            <div>
323                <h4>Encrypted Channels</h4>
324                <p>Private channels use AES-256 symmetric keys. Public channels are open. Direct messages are encrypted to the recipient's public key.</p>
325            </div>
326        </div>
327    </div>
328</div>
329
330<div class="section">
331    <h2>Getting Started</h2>
332    <p>Two options to join the network:</p>
333    <p>
334        <strong>Upload your config</strong> &mdash; already have a keypair? Upload your configuration file to rejoin your channels and contacts instantly.
335    </p>
336    <p>
337        <strong>Create a new identity</strong> &mdash; generate a fresh Ed25519 keypair and subscribe to default channels. Your keys are created locally and never touch a server.
338    </p>
339    <div class="cta-group" style="margin-top: 20px;">
340        <button onclick="document.getElementById('configFile').click()" class="btn btn-secondary">Upload Config</button>
341        <a href="/client" class="btn btn-primary">New Identity</a>
342    </div>
343    <p style="margin-top: 20px;">
344        Want to run your own node? Clone the repo and start contributing to network resilience:
345    </p>
346    <div class="auth-box" style="margin-bottom: 0;">
347        <div>git clone https://github.com/jmcentire/HermesP2P.git</div>
348        <div>cd HermesP2P && npm install && npm run start</div>
349    </div>
350</div>
351
352<div class="section">
353    <h2>Learn More</h2>
354    <div class="book-box">
355        <h3>Built on the ideas in <em>Privacy</em></h3>
356        <p>
357            The theoretical foundation behind HermesP2P's design decisions around ephemeral communication,
358            key sovereignty, and decentralized trust.
359        </p>
360        <a href="https://a.co/d/05PSJFBK" class="btn btn-secondary" style="margin-right: 8px;">Read the Book</a>
361        <a href="https://github.com/jmcentire/HermesP2P" class="btn btn-primary">View on GitHub</a>
362    </div>
363    <div style="text-align: center; margin-top: 16px;">
364        <a href="https://docs.google.com/presentation/d/1xYhkXgVJ6M-QtQr5NqtQpqmQN9M7kQOD8_eBW3R3yZY/edit?usp=sharing"
365           target="_blank" style="color: #6c757d; font-size: 0.9rem;">
366            View Presentation Deck
367        </a>
368    </div>
369</div>
370
371<div class="section" style="margin-top:24px;">
372    <h2>Privacy Stack</h2>
373    <p style="margin-bottom:12px;">HermesP2P is one layer of a larger privacy architecture.</p>
374    <div style="display:flex;gap:16px;flex-wrap:wrap;">
375        <a href="https://signet.tools" class="btn btn-secondary">Signet</a>
376        <a href="https://jmcentire.github.io/agent-safe/" class="btn btn-secondary">Agent-Safe</a>
377        <a href="https://jmcentire.github.io/tessera/" class="btn btn-secondary">Tessera</a>
378        <a href="https://jmcentire.github.io/BlindDB/" class="btn btn-secondary">BlindDB</a>
379    </div>
380</div>
381
382<footer>
383    <p>HermesP2P &middot; <a href="https://github.com/jmcentire/HermesP2P">GitHub</a> &middot; <a href="https://a.co/d/05PSJFBK">Privacy (Book)</a> &middot; <a href="mailto:[email protected]">[email protected]</a></p>
384</footer>
385
386<script>
387    document.getElementById('configFile').addEventListener('change', async function(e) {
388        const file = e.target.files[0];
389        if (!file) return;
390
391        const statusDiv = document.getElementById('uploadStatus');
392        statusDiv.className = 'alert alert-info';
393        statusDiv.textContent = 'Validating configuration...';
394        statusDiv.classList.remove('d-none');
395
396        const formData = new FormData();
397        formData.append('config', file);
398
399        try {
400            const response = await fetch('/validate-config', {
401                method: 'POST',
402                body: formData
403            });
404
405            const result = await response.json();
406
407            if (response.ok) {
408                statusDiv.className = 'alert alert-success';
409                statusDiv.textContent = 'Configuration valid! Redirecting to client...';
410                sessionStorage.setItem('hp2pConfig', JSON.stringify(result.config));
411                setTimeout(() => {
412                    window.location.href = "/client";
413                }, 1500);
414            } else {
415                statusDiv.className = 'alert alert-danger';
416                statusDiv.textContent = 'Error: ' + result.error;
417            }
418        } catch (error) {
419            statusDiv.className = 'alert alert-danger';
420            statusDiv.textContent = 'Error uploading configuration: ' + error.message;
421        }
422    });
423</script>
423
424
425<!-- WebMCP (A6): advertise a minimal tool to in-page AI agents via navigator.modelContext. -->
426<script>
427    (function() {
428        if (typeof navigator === 'undefined' || !navigator.modelContext || typeof navigator.modelContext.provideContext !== 'function') {
429            return;
430        }
431        try {
432            navigator.modelContext.provideContext({
433                tools: [
434                    {
435                        name: "get_site_info",
436                        description: "Return Hermes P2P metadata",
437                        inputSchema: { type: "object", properties: {} },
438                        execute: async () => ({
439                            site: "hp2p.net",
440                            description: "Hermes P2P — content-addressable pull-based P2P relay"
441                        })
442                    }
443                ]
444            });
445        } catch (e) { /* no-op: WebMCP is best-effort */ }
446    })();
447</script>
447
448
449</body>
450</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.