- DHT-01: docs/did-dht-integration.md — did:dht spec analysis, DNS packet encoding, mainline crate, publication/resolution flows, security notes - SCHEMA-01: docs/dwn-protocols.md — 4 DWN protocol definitions with JSON schemas: node-identity, file-catalog, federation, app-deploy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6.6 KiB
did:dht Integration Architecture
Overview
Archipelago currently uses did:key for node identities. This document describes integrating did:dht as a complementary DID method that makes node identities discoverable via the BitTorrent Mainline DHT, without relying on centralized registries, Nostr relays, or Tor hidden services.
Goal: Each Archipelago node has two DID types:
did:key— Offline, self-certifying, works without network (primary identity)did:dht— Published to Mainline DHT for decentralized discovery (optional, discoverable)
What is did:dht?
The did:dht method stores DID Documents in the BitTorrent Mainline DHT using BEP-44 (mutable items). Key properties:
- No server needed: Uses the public DHT network (~15M+ nodes)
- Ed25519 keypair: Same key type Archipelago already uses
- DNS-encoded: DID Document stored as a DNS packet (compact, standardized)
- Mutable: Documents can be updated by the key holder
- TTL-based: Published records have a TTL and must be refreshed periodically (every 2 hours recommended)
- Identifier format:
did:dht:{z-base-32-encoded-ed25519-pubkey}
Architecture
DID Relationship
Node Identity (Ed25519 keypair)
├── did:key:z6Mk... (derived from pubkey, offline, stable)
└── did:dht:z6Mk... (published to DHT, discoverable, same key)
Both DIDs use the same underlying Ed25519 keypair. The did:dht identifier is the z-base-32 encoding of the 32-byte public key. This means the same keypair produces both DID types — no additional key management.
DHT Publication Flow
1. Node generates Ed25519 keypair (already exists)
2. Node creates DID Document with:
- Ed25519 verification key (signing)
- X25519 key agreement key (derived)
- Service endpoints (optional: Tor onion, federation endpoint)
3. DID Document encoded as DNS packet (RFC 1035)
4. DNS packet signed with Ed25519 key (BEP-44 mutable item)
5. Published to Mainline DHT under the public key
6. Refreshed every 2 hours to maintain availability
DNS Packet Encoding
The DID Document maps to DNS resource records:
| Record Type | Name | Purpose |
|---|---|---|
TXT _did. |
vm=k0 |
Verification method: key 0 (Ed25519) |
TXT _did. |
auth=0 |
Authentication uses key 0 |
TXT _did. |
asm=0 |
AssertionMethod uses key 0 |
TXT _k0._did. |
id=0;t=0;k={base64url_pubkey} |
Key 0: Ed25519 public key |
TXT _s0._did. |
id=tor;t=TorHiddenService;se={onion} |
Service endpoint (optional) |
Resolution Flow
1. Receive did:dht:{identifier}
2. Decode z-base-32 → 32-byte Ed25519 public key
3. Query Mainline DHT for BEP-44 mutable item under that key
4. Verify signature on the DHT payload
5. Parse DNS packet → reconstruct DID Document
6. Cache for 1 hour (reduce DHT load)
Implementation Plan
Rust Crate: mainline
Use the mainline crate for Mainline DHT access. It provides:
Dht::client()for resolution-only nodesDht::server()for full DHT participationMutableItemfor BEP-44 put/get operations- Ed25519 signing compatible with
ed25519-dalek
Additional crates needed:
simple-dnsortrust-dns-protofor DNS packet encoding/decodingzbase32for z-base-32 encoding (did:dht identifier format)
New Files
core/archipelago/src/identity/
├── did_dht.rs — did:dht creation, publication, resolution
└── dns_packet.rs — DID Document ↔ DNS packet encoding
New RPC Endpoints
| Endpoint | Description |
|---|---|
identity.create-dht-did |
Publish current node's DID to DHT |
identity.resolve-dht-did |
Resolve a did:dht from the DHT |
identity.refresh-dht-did |
Force refresh the DHT publication |
identity.dht-status |
Check if node's did:dht is published and resolvable |
Integration Points
- Server startup: Optionally publish did:dht in background (non-blocking)
- Identity manager: Store did:dht alongside did:key in identity records
- Federation: Accept did:dht in peer join/discovery
- Web5 UI: Display both DID types, add publish/resolve buttons
- Credentials: Accept did:dht as issuer/subject in VCs
Background Refresh
A background tokio task refreshes the DHT publication every 2 hours:
spawn background task:
loop {
publish_to_dht(keypair, did_document_dns_packet)
sleep(2 hours)
}
If the node is offline when the TTL expires, the record drops from the DHT. It gets re-published when the node comes back online.
Security Considerations
-
Same key for both DIDs: No new key material to protect. The Ed25519 key already in
/var/lib/archipelago/identity/node_keyis used for both. -
DHT is public: Publishing to the DHT makes the node's DID Document visible to anyone querying the DHT. This is intentional for discoverability. Sensitive information (Tor addresses) should only be included in the service endpoints if the user explicitly opts in.
-
No Tor address by default: The DID Document published to DHT should NOT include Tor hidden service addresses by default (per the security rule about not publishing onion addresses publicly). Tor addresses are exchanged privately via federation.
-
BEP-44 signature verification: All DHT records are signed with Ed25519. Resolvers verify the signature, preventing tampering.
-
Sybil resistance: did:dht identifiers are derived from public keys, so creating a fake identity requires generating a new keypair. The federation trust system already handles this via trust levels.
Comparison: did:key vs did:dht
| Property | did:key | did:dht |
|---|---|---|
| Offline creation | Yes | No (needs DHT access) |
| Discoverable | No (must share manually) | Yes (query by identifier) |
| Persistence | Permanent (derived from key) | TTL-based (needs refresh) |
| Network requirement | None | UDP to DHT peers |
| Resolution | Local computation only | DHT query (~1-5s) |
| Privacy | Key not published anywhere | Key is on the DHT |
| W3C standard | Yes (DID Core) | Yes (DID Core) |
Timeline
- DHT-02: Implement did:dht creation + publication (~2 days)
- DHT-03: Implement did:dht resolution + caching (~1 day)
- DHT-04: Web5 UI integration (~1 day)
- Testing: Cross-node resolution via DHT (separate from Tor) (~1 day)