Blog

PIN pairing that can't be brute-forced: SPAKE2 for game streaming

A 4-digit PIN sounds weak — only 10,000 combinations. Here's how punktfunk pairs a new device with a PIN you can type from the couch while giving an attacker just one online guess and no offline dictionary attack, using a PAKE that binds both devices' certificates.

Pairing a new device to your streaming host should be as easy as typing a short code from the couch. But "short code" and "secure" usually pull in opposite directions: a 4-digit PIN is only 10,000 combinations, and if your pairing scheme leaks anything an attacker can test offline, those 10,000 guesses fall in milliseconds. punktfunk uses a short PIN and still makes brute force a non-starter. Here's how.

Why naive PIN pairing is weak

The obvious approach — send a hash of the PIN, or encrypt a known value with it — leaks a verifier: something an attacker who captured the handshake can grind against offline, trying all 10,000 PINs on their own hardware until one matches. Reverse-engineered GameStream pairing has had related weaknesses, and on the trust side, GameStream's TLS will accept essentially any client certificate. A short secret is only safe if a wrong guess tells the attacker nothing.

PAKE: prove you know the PIN without revealing it

punktfunk pairs with SPAKE2, a Password-Authenticated Key Exchange. The idea behind a PAKE is simple to state and subtle to build: both sides run a key exchange seasoned with the PIN, and they end up with the same shared key only if they used the same PIN. The PIN itself never crosses the network — and, crucially, a wrong PIN produces nothing testable offline. There's no captured verifier to grind.

That changes the economics completely. Instead of 10,000 offline guesses, an attacker gets exactly one online guess per pairing attempt: they have to actually talk to your host, in real time, and a miss is just a failed pairing. The PIN is single-use, so a failed or completed ceremony doesn't leave one lying around to retry.

What the ceremony actually binds

A pairing isn't just "the PIN matched." Each side has a persistent identity — a certificate it keeps across restarts. The SPAKE2 exchange binds both fingerprints: the host's and the client's. When the ceremony succeeds, each end pins the other's certificate. From then on the two recognize each other cryptographically, and the PIN has done its job and is gone.

After pairing: silent, mutual, and pinned

Once paired, reconnecting is silent — no PIN, no prompt — because both ends authenticate by the certificate they pinned during the ceremony. The host keeps a list of paired fingerprints and, by default, refuses sessions from devices that aren't on it. If a host's fingerprint ever changes (a reinstall, or something worse), the client doesn't quietly trust the new one — it forces you to pair again, on purpose.

Trust-on-first-use, but only when you ask for it

On a fully trusted LAN you can opt into trust-on-first-use instead: the host advertises that it's open, and the client offers a one-tap "Trust" for the first connection. That's an explicit host choice, not the default — PIN pairing is what new hosts do out of the box, and clients only offer the TOFU shortcut for a host that announced it allows it.

Approving from the couch

Because the host is often headless, you can also approve a pairing from the web console: an unpaired device shows up as a pending request, and one click approves and pins it. For the full walkthrough, see the pairing guide.