Skip to main content

Identity model

Every Crosslink device (host or client) has a long-term Ed25519 identity:
The identity is:
  • Generated once per installation
  • Persisted across restarts
  • Used to sign all key material
  • Verifiable by any peer

Pairing authentication

Step 1: Code generation

The host generates a single-use pairing code:

Step 2: Code resolution

The client sends the code to the signaling service:

Step 3: Fingerprint verification

The client verifies the host fingerprint from the QR code matches:
This is the primary MITM defense during pairing. If the fingerprints don’t match, an attacker is likely intercepting the signaling traffic.

Step 4: Signed claims

Both parties exchange signed public keys:

Step 5: Challenge-response

The host sends a challenge, and the client signs it:

Step 6: SAS verification

Both parties derive the same Short Authentication String from their Ed25519 identity public keys (order-independent, so both sides compute the same value regardless of role):
The user must visually confirm both sides show the same digits.

Session authentication

Once paired, sessions are authenticated via:
  1. Encrypted frames — Only parties with the session key can read/write
  2. Sequence numbers — Prevent replay attacks
  3. Nonce uniqueness — Prevent frame substitution

Key hierarchy

Revocation

Host revocation

The host can revoke a client’s access by:
  1. Calling server.revokeDevice(deviceId)
  2. This prevents future sessions from being established — revocation is re-checked on every handshake, so reconnection is refused even though the device still holds a valid Ed25519 key

Client revocation

The client can forget a paired host by:
  1. Calling client.forget(appId)
  2. This removes the paired-app record
  3. Future pairing requires a new QR scan

Security properties