# Default-key generators: reverse engineering the WPA shortcut

> Why the WPA passphrase printed on the bottom of so many ISP-supplied routers isn't actually random — a pattern, an abstract methodology, and why this kind of research matters for the defender side.

By Jeff Mixon, published 2021-11-08. Canonical: https://www.jeffmixon.com/post/wpa-default-key-reverse-engineering/

## The shape of the problem

Open the bottom of a router your ISP shipped you. There's a sticker with a
default Wi-Fi network name and a default WPA passphrase. In a meaningful
fraction of cases, that passphrase is not actually random — it is
*derived* from data that's also visible on the air, like the BSSID
(MAC address) or the SSID itself. Sometimes there's also a serial-number
component that isn't on the air, which raises the bar; sometimes there
isn't.

If the derivation function is recoverable, the passphrase becomes a
function of public information, and the security of the network reduces
from "an attacker needs to crack a strong passphrase" to "an attacker
needs to call a function." That is a substantially different threat
model, and it is the threat model some default configurations have
actually been in.

This is well-trodden research at this point — the academic and
hobbyist literature has covered specific vendor families in detail for
years, and tools like [`PSKracker`](https://github.com/soxrok2212/PSKracker)
exist as one-stop implementations of the well-understood families. What
I want to talk about here is the *shape* of the work, because the
methodology is more transferable than any individual algorithm.

## The recurring pattern

The pattern repeats across vendor families with almost-comical
consistency:

1. **A seed visible on the air.** Usually BSSID, sometimes SSID, sometimes
   both. Occasionally combined with something less-visible (serial number
   from the sticker, manufacture date encoded into the MAC range).
2. **A derivation function.** Sometimes a hash, sometimes a hash truncated
   to N characters, sometimes a custom mixing function, sometimes a
   selection-from-charset indexed by hash bytes. Almost always something
   that looks like it was designed by someone who knew it was a bad
   idea but went ahead anyway.
3. **A character set.** "Letters and digits, length 10" or similar.
   Frequently chosen for the readability of the sticker rather than for
   any cryptographic property.
4. **Per-firmware-revision drift.** The same vendor will sometimes change
   the function between firmware revisions, leaving a vulnerable window
   for the older firmware versions until a fleet upgrade rolls out.

Knowing the pattern means you know what to look for the next time you
encounter a new vendor family. Knowing it well means you can predict
which families are *likely* to have a derivation function before you've
even started looking.

## Abstract methodology

I have done a few of these from scratch. The methodology I keep coming
back to:

- **Collect.** Acquire a corpus of (BSSID, SSID, passphrase) triples
  for the target vendor family. The hardest part of the project is
  almost always this one — you need enough variation to distinguish a
  real relationship from a coincidence.
- **Look for the obvious.** Hash the visible identifiers with each
  common hash function, take the first N characters in each character
  set, compare. A frightening number of vendor algorithms are
  literally "SHA-1 of the BSSID, take the first ten hex digits."
- **Slice by firmware.** If the obvious doesn't work corpus-wide, slice
  by firmware revision. Vendors change algorithms.
- **Reverse the actual firmware** if it does. Once you suspect there is
  a derivation function, the binary that ships on the device contains
  it. This is where Binwalk and Ghidra come in.
- **Validate.** A candidate algorithm has to predict the passphrase
  for *every* triple in your corpus, not just enough of them to be
  encouraging. The discipline that catches you when you've found a
  coincidence rather than a function is testing against a held-out set.
- **Compare to public.** Once you have something that validates, check
  against the public literature for that vendor. If someone has already
  published the same algorithm, your work is independent confirmation
  rather than novel disclosure — which is the responsible position to
  be in.

## Why this matters for the defender side

The reason any of this is worth doing as a personal-research line —
beyond it being interesting — is that defenders need to know what
attackers know. If you are a network operator handing out devices to
end users, you need to know whether the firmware you're shipping has
its own default-key algorithm waiting to be reversed. If you are an
auditor, you need to know which vendor families' defaults are already
public so you can flag them in field surveys without doing the work
again. If you are a researcher, you need to be able to recognize the
pattern when it crosses your desk.

I've kept a small private collection of from-scratch Python
implementations for the families I've worked through, plus a working
knowledge of `PSKracker`'s coverage of the well-documented families.
The private implementations don't add anything to the public corpus —
they're independent confirmations of work others have already done —
but doing them is what built the intuition.

## What I won't write down here

The specific vendor families I've worked on personally — and any
implementation details that aren't already in the public literature —
stay off this page. The methodology generalizes; novel algorithm
disclosure belongs in a coordinated-disclosure track, not on a personal
blog.

## Closer

"Default credentials are bad" is the kind of advice that has been
boring for so long that people stop hearing it. Reversing a default-key
algorithm is the visceral version of the same lesson: *the only way for
a default to be safe is for it to be the output of a real RNG, written
down at provision time and recoverable nowhere else.* Anything else
eventually gets reversed by someone with a corpus and a weekend.
