Pairing flow
Pairing runs over whichever route the client reaches the host on. There are two, and the cryptographic exchange is identical either way: Direct — the client opens a WebSocket straight to the host using a route from the QR (lan on the same network, wan through a router mapping). No
service is involved at all. This is the default and needs no infrastructure.
Brokered — for a host reachable neither way, a signaling service relays the
same frames between the two sides.
Pairing code
Format
Properties
Generation
Pairing URI
The QR encodes a pairing URI carrying a list of routes, not one URL:
Endpoint kinds are
lan, wan, sig, relay and tunnel, and the client
attempts them in that order. A real example:
lan or wan route: on
the phone, 127.0.0.1 is the phone.
Version 1 URIs (v=1&s=<signalingUrl>) still parse, and are read as a single
sig endpoint.
Delivering the URI to a phone
iOS has no handler for a custom scheme, so a camera app will refuse to opencrosslink:// directly. Hosts put the pairing URI in the fragment of an ordinary
HTTPS/HTTP bootstrap URL instead:
SAS verification
Short Authentication String (SAS) digits are derived from:Fingerprint pinning
The QR code includes the first 16 hex characters of the host’s Ed25519 fingerprint:Pairing options
Host-side options
Client-side options
Re-pairing
If a device loses its paired record:- Generate a new pairing code
- Scan the QR code again
- Complete the pairing flow
- The old paired record is replaced
Security considerations
- Single-use codes prevent replay attacks
- Short TTL limits the window for interception
- Fingerprint pinning prevents MITM by a compromised signaling service, or by anything else that can relay a host’s address while substituting its own identity
- SAS verification confirms no active attacker
- Capability scoping limits blast radius of compromised client