⚡ CODE DEEP DIVE wiltkey_server Analysis

Go Blind Relay Protocol & Server Architecture

Comprehensive code analysis of the Go Blind Relay: Ed25519 GATT Challenge-AUTH, dynamic RAM load fallbacks, token-gated S3 file streaming, token bucket flood guards, and proxy security.

Interactive Relay Storage Routing & RAM Pressure Engine

Adjust system RAM load and message payload size below to observe how the relay dynamically routes traffic between Redis Sorted Sets, Postgres Inline Storage, and S3 Object Storage.

Simulated System RAM Load: 42% (Normal)
Payload Size: 120 KB (Small)
ACTIVE STORAGE DESTINATION:
Redis Sorted Set Queue (Memory Mailbox)
Payload < 500 KB and RAM < 80%. Enqueued in Redis sorted set keyed by recipient ID. TTL: 24h (Free) / 72h (Plus).
SERVER ROUTING TRACE
[19:02:10] WS/SEND_MESSAGE payload length: 122,880 bytes
[19:02:10] checkMemoryPressure(): RAM 42% < 80% threshold
[19:02:10] rdb.AddMessageToQueue("usr_a1b2...", msg) → Redis OK
[19:02:10] Delivery status: Enqueued for offline recipient

1. Zero-Knowledge Architecture & Identity Derivation

The Wiltkey Blind Relay acts as a blind mailbox. It coordinates client routing and temporary message queuing without acquiring metadata about relationships, user identities, or plaintext contents. Authentication relies entirely on client Ed25519 identity keypairs exchanged face-to-face over BLE.

Opaque User ID Generation

The relay identifies users exclusively by the hex-encoded digest of SHA-256(Ed25519_pubkey). There are no registration forms, email requirements, phone numbers, or persistent user accounts on the relay:

// auth.go (wiltkey_server) func GenerateUserID(publicKeyBytes []byte) string { hash := sha256.Sum256(publicKeyBytes) return hex.EncodeToString(hash[:]) }

2. GATT Ed25519 Challenge-Response Auth Sequence

When a client connects to the WebSocket endpoint (/ws), the server executes `ServeWS` (in websocket.go). Connections must prove ownership of their identity public key within 5 seconds before any message routing is permitted.

// 1. Server generates random 32-byte hex challenge and writes CHALLENGE frame challengeBytes := make([]byte, 32) rand.Read(challengeBytes) challengeHex := hex.EncodeToString(challengeBytes) conn.WriteJSON(WSMessage{Type: "CHALLENGE", Challenge: challengeHex}) // 2. Client must reply with AUTH frame within 5 seconds conn.SetReadDeadline(time.Now().Add(5 * time.Second)) ok, err := VerifySignature(authMsg.Pubkey, authMsg.Signature, []byte(challengeHex)) if err != nil || !ok { conn.Close() // Drop unauthenticated connection return }

AUTH_OK Capability Advertising

Upon verification, the relay responds with AUTH_OK and advertises server capabilities (such as group_fanout). This allows client devices to enable single-upload group delivery when supported by the connected relay while retaining backwards compatibility with self-hosted instances.

3. Three-Tiered Storage & RAM Load Fallback Engine

When routing a message (via WebSocket SEND_MESSAGE or REST POST /api/v1/queue/post), the relay executes a three-tiered storage decision based on payload size and system memory pressure:

Tier 1: Redis Sorted Set Mailbox (<500 KB, RAM <80%)

Under normal conditions, offline messages under 500 KB are stored in Redis sorted sets keyed by recipient ID. To prevent memory exhaustion attacks, each recipient queue is bounded by maxQueueLen = 1000. When exceeded, the oldest entries are dropped. Offline hold TTL is keyed on recipient subscription tier (24 hours for free recipients, 72 hours for Plus subscribers).

Tier 2: Postgres Inline Fallback (<500 KB, RAM ≥80%)

If system memory load rises to 80% or above (monitored by checkMemoryPressure() via v.UsedPercent >= thresholdPercent in main.go:L845), the relay automatically bypasses Redis RAM and writes offline messages directly into Postgres inline table storage (pg.StoreMessageInline) to protect server RAM.

Tier 3: Token-Gated S3 Object Storage (≥500 KB up to 50 MB)

For file payloads ≥500 KB (up to the 50 MB Plus limit), the relay uploads the encrypted envelope to S3-compatible Object Storage (storage.Upload). It strips the bulky d ciphertext field to build a lightweight FILE_OFFER frame (metadata only):

  1. The recipient receives a FILE_OFFER WebSocket frame containing message ID, sender ID, size, and metadata.
  2. When the recipient taps to download, the client sends a REQUEST_FILE frame.
  3. The relay verifies authorization, issues a short-lived download token, and returns a FILE_TOKEN frame.
  4. The client streams the file via HTTP GET /api/v1/file?token=... with progress bars.
  5. The S3 object and Postgres metadata row are deleted ONLY after the recipient's client issues a FILE_RECEIVED WebSocket ACK.

4. Abuse Protections, Token Bucket Flood Guards & Reverse Proxy Safety

Because clients authenticate using Ed25519 identity keypairs and stamps are crypto-verified, senders cannot forge their `sender_id`. To protect against availability/DoS attacks, the relay implements multi-layered guards:

Per-Socket Token Bucket Flood Guard

Each authenticated WebSocket connection runs a token bucket in `readPump` (in websocket.go:L27–L30):

const ( wsBucketCapacity = 200.0 // Max burst capacity (group fan-out, resync) wsRefillPerSec = 100.0 // Sustained message refill rate per second )

Reverse Proxy Real IP Resolution (`clientIP()`)

HTTP rate limits and bans are keyed on client IP. When the relay sits behind a reverse proxy (e.g. Nginx, Caddy), every connection arrives from 127.0.0.1 unless headers are forwarded. In `main.go`, `clientIP()` verifies that the direct peer is loopback before trusting X-Real-IP or X-Forwarded-For:

🚨 PROXY CONFIGURATION INVARIANT
If the reverse proxy fails to set X-Real-IP or if the relay trusts untrusted headers from external peers, all users share a single rate-limit bucket. One abuser will throttle all users, and a single IP ban will lock out the entire userbase.

5. Function-to-Function Server Code Walkthrough

Go Symbol File Location Description & Key Behavior
ServeWS() websocket.go:L382 Upgrades HTTP connection to WS, issues 32B random challenge, verifies Ed25519 AUTH signature, registers client in Hub.
handleSendMessage() handlers.go:L17 Enforces 50MB ceiling, 5MB premium gate, checks RAM load, uploads ≥500KB payloads to S3, or enqueues in Redis/Postgres.
handleBroadcastGroupMessage() handlers.go:L142 Processes single-upload group messages, delivering the payload to each recipient socket/queue with zero-knowledge blindness.
handleRequestFile() & handleFileReceived() handlers.go:L310 Mints short-lived download tokens for S3 streaming and processes `FILE_RECEIVED` ACKs to purge stored objects.
AddMessageToQueue() redis.go:L150 Enqueues small offline envelopes in Redis Sorted Sets; enforces `maxQueueLen = 1000` cap to prevent memory exhaustion.
clientIP() main.go:L790 Resolves real client IP by checking loopback peer status before evaluating `X-Real-IP` / `X-Forwarded-For` headers.