Security

Threat model in one paragraph

The server and the network are not trusted: they may log, block or tamper with traffic. Someone who knows your ID but not your password shouldn't be able to see your screen, and shouldn't get a useful offline guess at the password either. Anyone who knows the password is treated as authorized.

Password handshake (SPAKE2)

Passwords are never sent, not even hashed. Instead both computers run SPAKE2, a password-authenticated key exchange: they derive the same session key only if they used the same password, and an eavesdropper or a man in the middle (including the server) learns nothing that would let them test password guesses offline. Each connection attempt gives an attacker at most one online guess.

The host has two password slots, the one-time password and the optional permanent one. The viewer runs one SPAKE2 exchange per slot in the same round trip, then proves which one succeeded with an HMAC confirmation tag. The host answers with its own tag, so the viewer also knows it reached a computer that knows the password.

Session encryption

After the handshake:

  • HKDF-SHA256 derives one key per direction from the shared secret.
  • Every message is sealed with ChaCha20-Poly1305 using a counter as the nonce, so a replayed, reordered or modified message fails to decrypt and ends the session.
  • This is the same on every route (LAN, peer-to-peer and relay).

Peer-to-peer connections additionally run inside QUIC, whose TLS layer uses a throwaway self-signed certificate. That certificate isn't checked against anything, on purpose: QUIC's TLS is only an extra transport layer, and authentication comes from SPAKE2 inside it.

Host-side protections

  • Lockout: 5 wrong passwords within a minute block further attempts for the rest of that minute.
  • Ask before connecting: require a local click to accept, even with the right password.
  • Live permissions: revoke control, clipboard or file reception during a session.
  • Safe file names: received names are reduced to a plain file name, so they can't escape Downloads/Remora.
  • Clipboard privacy: what's on your clipboard when a session starts isn't sent.

Known limitations

LimitationImpact
The permanent password is stored in plain text in config.jsonAnyone who can read your user profile can read it. Moving it to the OS keychain is planned.
IDs aren't bound to a device keyWhile you're offline, someone else could register your ID on the same server. They still can't complete a handshake without your password, but they could block people from reaching you. Device keys that prove ownership are planned.
No two-factor authentication or audit log yetPlanned.
Direct connections are open to anyone who can reach the portKeep a strong password, or turn direct connections off.

Recommendations

  • Prefer the one-time password; use a long permanent password only where you need unattended access.
  • Run your own server rather than someone else's.
  • Turn on Ask before connecting on machines where a person is usually present.