Fredrik Johansson 3e058bee9b Migrate to YAW/2 protocol: WebRTC transport, anchor signaling, nacl/box crypto
Replace the original raw-TCP peer connections and Blowfish/RSA-era design with
the YAW/2 protocol stack:

Transport
- internal/mesh/peer.go: raw TCP + manual ECDH replaced with pion/webrtc
  DataChannels (ICE, DTLS, SCTP). Peers negotiate via sealed offer/answer/
  candidate exchange rather than direct dialling.
- internal/nat: deleted — ICE subsumes everything this package was going to do.

Signaling
- cmd/anchor: new WebSocket signaling server (replaces cmd/relay). Verifies
  Ed25519 challenge/join signatures, routes opaque nacl/box blobs, broadcasts
  peer-join/peer-leave events. Never sees plaintext signaling content.
- internal/anchor: new anchor client. Manages PeerConnection lifecycle,
  decides offerer by peer-id comparison, seals/opens signaling payloads with
  nacl/box, implements mesh.Anchor.

Crypto (internal/crypto)
- PeerID encoding: base64url → lowercase hex (64 chars, YAW/2 §2).
- Sign/Verify: hex signatures throughout.
- Added CurvePublicKey/CurvePrivateKey: X25519 keys derived from Ed25519
  identity via Montgomery conversion (filippo.io/edwards25519), matching
  libsodium's crypto_sign_ed25519_*_to_curve25519.
- Added SignalingBox/SignalingOpen: nacl/box (XSalsa20-Poly1305) seal/open
  for signaling payloads.

Wire types (internal/proto)
- ChatMessage gains Mid (random 16-byte hex) for mesh deduplication (§8).
- FileChunk removed from PeerMessage — chunks go on a separate binary
  DataChannel labelled "f:<xid>"; FileDone added.
- New types: SignalingPayload, AnchorMessage, HelloMessage, HelloBindString.
- PeerID.Short() now returns first 16 hex chars grouped in 4s.
- IPC: CmdConnect removed; CmdJoinNetwork/CmdLeaveNetwork added;
  EvtSessionReady added (fires when DataChannel opens and hello is received).

IPC (internal/ipc)
- join_network/leave_network replace connect (direct TCP dial).
- Network joins are context-scoped: leave_network or client disconnect
  cancels the anchor connection cleanly.

README updated to reflect new project layout, getting-started commands,
IPC protocol, and roadmap state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 17:48:14 +02:00
2026-06-21 16:14:07 +02:00
2026-06-21 16:14:07 +02:00

waste-go

A modern reimagining of WASTE — decentralized, friend-to-friend encrypted mesh networking with chat and file sharing. Written in Go.

Project layout

waste-go/
├── cmd/
│   ├── daemon/      The peer process — run one on each friend's machine
│   └── anchor/      WebSocket signaling server — run this on your Hetzner VPS
└── internal/
    ├── proto/       All wire types (shared by daemon and anchor)
    ├── crypto/      Ed25519 identity, nacl/box signaling, ChaCha20-Poly1305
    <20><><EFBFBD>── mesh/        Connected peer state + DataChannel helpers
    ├── anchor/      Anchor client — WebRTC signaling via the anchor server
    └── ipc/         Local JSON API (UI talks to daemon here, port 17337)

Prerequisites

On first open VS Code will prompt you to install gopls, dlv, and goimports — accept all of them.

Getting started

# Fetch dependencies
go mod tidy

# Build everything (confirms it compiles)
go build ./...

# Terminal 1 — anchor (required for peers to find each other)
go run ./cmd/anchor -bind 127.0.0.1:17339

# Terminal 2 — peer A
go run ./cmd/daemon -alias alice -data-dir /tmp/waste-alice -ipc-port 17337 -anchor ws://127.0.0.1:17339/ws

# Terminal 3 — peer B
go run ./cmd/daemon -alias bob -data-dir /tmp/waste-bob -ipc-port 17341 -anchor ws://127.0.0.1:17339/ws

Both peers join the same named network via IPC:

# Join peer A to a network called "friends"
echo '{"type":"join_network","network_name":"friends"}' | nc 127.0.0.1 17337

# Join peer B to the same network
echo '{"type":"join_network","network_name":"friends"}' | nc 127.0.0.1 17341

# Subscribe to peer A's events (in a separate terminal)
nc 127.0.0.1 17337 &

# Send a message from B
echo '{"type":"send_message","room":"general","body":"hello from bob"}' | nc 127.0.0.1 17341

On Windows — use PowerShell's built-in TCP client instead of nc:

$c = [System.Net.Sockets.TcpClient]::new('127.0.0.1', 17341)
$w = [System.IO.StreamWriter]::new($c.GetStream()); $w.AutoFlush = $true

$w.WriteLine('{"type":"join_network","network_name":"friends"}')
$w.WriteLine('{"type":"send_message","room":"general","body":"hello from bob"}')

# In a separate terminal — subscribe to peer A's events
$r = [System.Net.Sockets.TcpClient]::new('127.0.0.1', 17337)
$reader = [System.IO.StreamReader]::new($r.GetStream())
while ($true) { $reader.ReadLine() }

Deploying the anchor on your Hetzner VPS

GOOS=linux GOARCH=amd64 go build -o bin/waste-anchor ./cmd/anchor
scp bin/waste-anchor user@your-vps:~/

# On the VPS (also run coturn in STUN-only mode on port 3478)
./waste-anchor -bind 0.0.0.0:17339

Then start daemons with -anchor ws://your-vps-ip:17339/ws and they'll connect via WebRTC with ICE (STUN-assisted hole punching) through the anchor for signaling.

IPC protocol (plain JSON over TCP)

Everything is newline-delimited JSON. You can test with nc 127.0.0.1 17337.

Commands you send:

{"type":"join_network","network_name":"friends"}
{"type":"leave_network"}
{"type":"send_message","room":"general","body":"hi"}
{"type":"get_state"}

Events the daemon pushes:

{"type":"state_snapshot","local_peer":{...},"connected_peers":[...]}
{"type":"peer_connected","peer":{...}}
{"type":"session_ready","peer_id":"<hex>","nick":"alice"}
{"type":"message_received","message":{"from":"<hex>","body":"hi","room":"general"}}
{"type":"peer_disconnected","peer_id":"<hex>"}

Crypto choices

Purpose Algorithm Notes
Identity Ed25519 Fast, small keys, standard
Peer ID Hex-encoded Ed25519 pubkey 64 lowercase hex chars (YAW/2 §2)
Signaling encryption XSalsa20-Poly1305 (nacl/box) X25519 keys derived from Ed25519 identity (YAW/2 §3)
Transport WebRTC DataChannels (DTLS+SCTP) pion/webrtc — ICE, hole punching included
Hashing SHA-256 File integrity, network name hashing

Replaces WASTE's original Blowfish/PCBC (broken cipher mode) + RSA.

Peer IDs are 64-char lowercase hex (Ed25519 public key). Existing identity.json files on disk are unaffected — only the over-the-wire representation changed from base64url.

Roadmap

  • Crypto layer — hex peer IDs, nacl/box signaling, Ed25519→X25519 key derivation
  • Proto additionsmid field, signaling types, anchor wire types, hello message, FileDone
  • Anchor server (cmd/anchor) — WebSocket signaling server (replaces TCP relay)
  • WebRTC peer connections — pion/webrtc DataChannels replace raw TCP in internal/mesh
  • Anchor client (internal/anchor) — ICE offer/answer/candidate lifecycle, nacl/box sealing
  • IPC updatesjoin_network/leave_network replace connect; session_ready event added
  • File transfer — chunked binary DataChannel (f:<xid>)
  • Message persistence — SQLite via modernc.org/sqlite
  • TUI — Bubble Tea client consuming the IPC port
  • Native UI — web frontend with native packaging (Tauri-style)
Description
No description provided
Readme 1.8 MiB
v0.1.6 Latest
2026-07-02 18:35:57 +02:00
Languages
Go 52.1%
TypeScript 30.2%
Shell 12%
CSS 5.2%
HTML 0.3%
Other 0.2%