OverviewFilesCommitsIssuesDocsReleasesPeers

atproto-identity commits / 6010c83

atproto-identity: discoveryTopic(did) — DID-derived P2P rendezvous (Option 2)
Deterministic 32-byte Hyperswarm topic from a DID (blake2b of a namespaced DID). The "sneaky P2P" discovery binding: nothing is written to the DID doc (it stays vanilla atproto — bsky sees only atproto_pds -> the bridge), yet a bridge can derive the same topic from the DID, find the peer, and authenticate it on connect (the served repo must sign against the DID key — a topic squatter can't forge it). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6010c8355ab76472a061d83785e046cde8f7aeee
by plankatron <fleeky@gmail.com> · 2026-07-03T22:27:23.000Z

Changed files (1) +18 -0

lib/discovery.js +18 -0
……@@ -0,0 +1,18 @@
1// DID-derived P2P discovery (the "sneaky P2P" binding, Option 2).
2//
3// The rendezvous topic for a DID is DERIVED, not written anywhere: the DID document stays
4// 100% vanilla atproto (only atproto_pds -> the bridge), so bsky/HTTP never sees a P2P side.
5// A self-custody peer announces on discoveryTopic(did); a bridge, given the DID, derives the
6// SAME topic, connects, and AUTHENTICATES the peer on connect (the peer's served repo must
7// sign against the DID's key — a squatter on the public topic can't forge that). So the lookup
8// is deterministic + unauthenticated; trust is established at the connection, not the address.
9
10import crypto from 'hypercore-crypto'
11
12const NS = 'hyper-peer/discovery/v1:'
13
14// did (string) -> 32-byte Hyperswarm topic. Deterministic; anyone with the DID can compute it.
15export function discoveryTopic (did) {
16 if (!did || typeof did !== 'string') throw new Error('discoveryTopic: did (string) required')
17 return crypto.data(new TextEncoder().encode(NS + did))
18}