Skip to content

Encrypt the stream, keyed to the pairing that already happens #83

Description

@nbkdoesntknowcoding

Where things stand

Video and input cross the LAN as a plain WebSocket. Access is gated by a 4-digit PIN exchange, and a paired device carries a token afterwards — so an unpaired machine gets nothing.

What that does not do is protect the traffic from anyone already on the network. Your screen, and every keystroke forwarded to the Mac, are readable by anything that can see the packets. SECURITY.md names this as a known trade rather than a vulnerability, and says a report asking for it is a welcome feature request.

This is that request.

What makes it interesting here

The usual answer is TLS, and the usual obstacle is certificates: there is no CA, the Mac has no domain name, and a self-signed certificate produces exactly the warning this project already refuses to normalise elsewhere.

But there is already a shared secret. Pairing establishes a token, held on both sides. That is enough to key a channel without any certificate authority at all — the same shape as Syncthing's device IDs, or a Noise handshake with a pre-shared key.

Roughly:

  • First pairing: authenticated key exchange over the existing PIN flow. The PIN is short and human-typed, so it needs a PAKE — SPAKE2 or CPace — rather than being used as key material directly.
  • Afterwards: the stored token authenticates the device, and each session derives fresh keys from it. Compromising a recording must not compromise the next session.
  • The transport underneath stays a WebSocket, so the framing and the golden vectors are untouched.

Constraints

  • The wire format is specified in protocol/SPEC.md and verified against golden vectors from both implementations. Encryption belongs under the framing, not woven into it.
  • Latency is the product. This is a live stream, not a file transfer. A handshake per session is fine; anything per frame needs to be measured, and there is now per-stage instrumentation to measure it with.
  • Both ends must move together. Swift on one side, Rust on the other, and a version mismatch has to fail comprehensibly rather than by hanging.

What would make a proposal convincing

Start with the design, not the code. Which handshake, why that one, what happens on downgrade, what happens when one end is older — and what it costs, measured, on the path that currently carries 1080p60.

Metadata

Metadata

Assignees

No one assigned

    Labels

    deep-diveSubstantial work — needs real expertise in one areaenhancementNew feature or requestprotocolTouches the wire format or its golden vectors

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions