Skip to main content
After pairing, the desktop gives the device a “membership card.” Later, the device proves it’s the real owner of that card. The gateway checks the card and the proof before allowing traffic through.

The three pieces

  1. The Root Node has a master key (private key) it never shares. It acts as the authority that can sign approvals for devices.
  2. Each device has its own keypair. The private key stays on the device; the public key is shareable.
  3. The gateway knows the Root Node’s public key. This lets the gateway verify that any approval was genuinely signed by the Root Node.

Phase 1: Pairing (one-time)

Step A — Device creates an identity

The device generates a keypair:
  • device_private_key — secret, stored on the device
  • device_public_key — sent to the Root Node during pairing

Step B — Root Node issues an approval

The device sends to the Root Node (via the gateway):
  • A short-lived pairing code (proves physical proximity to the Root Node UI)
  • device_public_key
The Root Node creates and signs an approval blob:
{
  "device_id": "phone-1",
  "device_public_key": "...",
  "expires_at": "2026-03-01T00:00:00Z"
}
The Root Node signs this blob with its private key and returns both pieces to the device:
  • approval_blob
  • desktop_signature_over_blob
Together these form the Device Attestation — the desktop-approved membership card. The device stores it.

Phase 2: Authentication (every connection)

Step 1 — Device connects to the gateway

The device opens a WebSocket connection to the gateway.

Step 2 — Gateway issues a challenge

The gateway sends a random nonce:
nonce = "938475..."
The nonce prevents replay attacks — copying an old auth message does not work because the nonce changes every time.

Step 3 — Device responds with two things

The device sends:
  1. The attestationapproval_blob + desktop_signature_over_blob
  2. A proof of key ownership — the device signs the nonce using its device_private_key, producing device_signature_over_nonce

What the gateway checks

The gateway performs two verifications: Check 1 — Is the attestation legit? The gateway verifies desktop_signature_over_blob using the Root Node’s public key. If valid, the card was signed by the Root Node and not forged. Check 2 — Does the device own the card? The attestation contains device_public_key. The gateway uses it to verify device_signature_over_nonce. If valid, the connecting device holds the matching private key — it is the real device, not someone who copied the blob. If both checks pass, the gateway marks the socket as authenticated as device_id=phone-1 and allows routing. If either check fails, the gateway closes the connection.

Why both checks are required

Missing checkAttack it enables
No attestation checkAnyone can generate a keypair and claim to be allowed
No ownership proofAnyone who copies the attestation blob can impersonate the device
Together they mean: the Root Node approved this device key, and the connecting device really owns that key.

Root Node authentication

The Root Node’s server process uses the same mechanism:
  • The Root Node has its own keypair
  • It signs an attestation for itself (or is treated as the trust root)
  • The gateway verifies it the same way
This lets the gateway enforce that only devices approved by a specific Root Node can communicate with that Root Node’s connection.

Revoking a device

The Root Node maintains a list of allowed device IDs. When you revoke a device, the gateway can handle it in two ways:
  • Short expiry — attestations expire after a set period (e.g. 7 days). The device stops working when the card expires.
  • Live check — the gateway asks the Root Node “is this device still allowed?” on each connection. This revokes access immediately.