# Why WPA3 won't do PPSK (yet)

In my last post I made a promise, I’d write about why WPA3 isn’t (yet) fully supported for PPSK across vendors. It’s a bit more theoretical and maybe not for the less technical, so grab a coffee. We’ll take some captures, look at what WPA2 actually does under the hood, and then walk into WPA3 and see exactly where it all falls apart.

Quick recap for anyone who skipped my last blog:

PPSK (Private Pre-Shared Key) gives every user their own password on the *same* SSID. Cisco calls it iPSK, Aruba, Fortinet and Mist call it MPSK, Ruckus calls it DPSK. Same idea everywhere, you use one network name, many keys, revoke one without touching the rest. It's heaven for every IT-admin.

The interesting part isn't the portal that hands out the keys. It's a question nobody really asks. A hundred users share one SSID, each with a different password, so how does the AP know which key you typed? It never asks for a username. You just type a password and you're on.

The answer lives in the 4-way handshake. And it’s also the reason WPA3 says 'nope'.

## Part 1) WPA2 PPSK under the hood

Let’s start with where the key even comes from. On a WPA2-Personal network, your passphrase isn’t used directly. It’s stretched into a 256-bit Pairwise Master Key (PMK):

`PMK = PBKDF2(HMAC-SHA1, passphrase, SSID, 4096 iterations, 256 bits)`

Two things to notice. The PMK depends only on your **passphrase** and the **SSID** (the SSID is the salt, which is why rainbow tables where all the passwords are precomputed don’t port between networks). And on a normal PSK network everyone derives the *same* PMK, because everyone types the same password. On a PPSK network, every user types a *different* password, so every user has a *different* PMK. Hold that thought, it’s the whole trick.

Now the handshake. After you associate, the AP (the authenticator) and your device (the supplicant) run the classic 4-way EAPOL exchange to prove you both know the PMK without ever sending it. Here’s what’s actually on the air:

<table style="min-width: 317px;"><colgroup><col style="min-width: 25px;"><col style="width: 108px;"><col style="width: 159px;"><col style="min-width: 25px;"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>Msg</p></td><td colspan="1" rowspan="1" colwidth="108"><p>Direction</p></td><td colspan="1" rowspan="1" colwidth="159"><p>Carries</p></td><td colspan="1" rowspan="1"><p>What it proves</p></td></tr><tr><td colspan="1" rowspan="1"><p>M1</p></td><td colspan="1" rowspan="1" colwidth="108"><p>AP → client</p></td><td colspan="1" rowspan="1" colwidth="159"><p>ANonce (random)</p></td><td colspan="1" rowspan="1"><p>"Here's my nonce."</p></td></tr><tr><td colspan="1" rowspan="1"><p>M2</p></td><td colspan="1" rowspan="1" colwidth="108"><p>client → AP</p></td><td colspan="1" rowspan="1" colwidth="159"><p>SNonce + <strong>MIC</strong></p></td><td colspan="1" rowspan="1"><p>“Here’s mine, and proof I derived the keys.”</p></td></tr><tr><td colspan="1" rowspan="1"><p>M3</p></td><td colspan="1" rowspan="1" colwidth="108"><p>AP → client</p></td><td colspan="1" rowspan="1" colwidth="159"><p>GTK + MIC</p></td><td colspan="1" rowspan="1"><p>“Agreed, here’s the group key.”</p></td></tr><tr><td colspan="1" rowspan="1"><p>M4</p></td><td colspan="1" rowspan="1" colwidth="108"><p>client → AP</p></td><td colspan="1" rowspan="1" colwidth="159"><p>ACK + MIC</p></td><td colspan="1" rowspan="1"><p>“Done.”</p></td></tr></tbody></table>

(Every one of these frames also gets a tiny 802.11 ACK at the MAC layer, I’ve filtered those out here to keep the four-message story clean.)

Between M1 and M2, your device computes the Pairwise Transient Key, the actual set of session keys. It's mixed together from the master key (PMK), both devices' MAC addresses, and the two random nonces. The part that matters is this. Every one of those ingredients except the PMK travels across the air in the clear. The only real secret in the mix is the one that came from your password.

The first chunk of that PTK is the Key Confirmation Key (KCK). Your device uses the KCK to sign M2 with a Message Integrity Check (MIC). That MIC is the magic. It’s a fingerprint that only comes out right if you used the correct PMK, which means the correct password.

![See below point 1](https://cdn.hashnode.com/uploads/covers/6a1aa4222365cdee7fc9b999/6bdbe870-e53b-4d4c-8ff3-7b3ad878d54b.png align="center")

Here's the part that makes PPSK possible. Look at what the AP has once M2 arrives. It sent the ANonce, so it knows that. It just received the SNonce and the MIC. It knows both MAC addresses. The only unknown left in the PTK equation is the PMK, and the PMK comes straight from the password.

So the AP does something cheeky. It walks its database of PPSK keys and, for each candidate, derives that key's PMK, derives the PTK, computes what the MIC should be, and compares it to the MIC you actually sent. One of them matches. That's you. That's your user, your VLAN, your policy.

![](https://cdn.hashnode.com/uploads/covers/6a1aa4222365cdee7fc9b999/8325f94c-e667-4fb5-8eca-7301d14792e5.png align="center")

No username. No certificate. The handshake itself leaks enough for the AP to *reverse out* which password you used. Extreme's own documentation puts it more bluntly than I would. PPSK relies on WPA2 because it “allows reverse-engineering of the passphrase based on its contribution to the master session key.” That’s not a side effect. For PPSK, it’s the entire feature.

## What the AP actually shows (from the CLI)

You don’t need the dashboard to watch this happen. SSH into the AP and run *show auth*. On my AP3000 the StageNet PPSK SSID looks like this (trimmed):

`if=wifi1.1; SSID=StageNet; PPSK-enabled=yes; use external server=yes; mac-bind=disabled; Protocol-suite=WPA2-AES-PSK; CWP is enabled;`

`No. Supplicant      UID  PMK    PTK    Life  State  Cipher`  
`--- --------------  ---  -----  -----  ----  -----  ---------`  
`0   baef:cac5:116a  0    79be*  0717*  7142  done   WPA2/CCMP`

Read that station row from the AP’s side of the same story: the client baef:cac5:116a has a **PMK** and a **PTK** derived, and **State = done**. That means the 4-way handshake completed and the MIC matched. It’s the M2 frame above, seen from inside the authenticator.

Now look one line up: use external server=yes. This AP isn’t holding the key database, it resolves keys against the cloud PPSK server. Which is exactly why the **User-Name column comes back empty**: the AP can prove it validated someone and derived keys, but the human identity lives in the cloud. The crypto is local, the name is not. One command and the whole cloud-versus-AP split falls right out of it.

![](https://cdn.hashnode.com/uploads/covers/6a1aa4222365cdee7fc9b999/78c93cc7-5892-4c93-bccc-658b815875a2.png align="center")

## Part 2) WPA3 and SAE, where the trick dies

WPA3-Personal throws out the PSK handshake and replaces it with **SAE**, Simultaneous Authentication of Equals, also known by its codename *Dragonfly*. SAE is a PAKE, a *Password-Authenticated Key Exchange*, and it was designed specifically to kill the thing PPSK depends on, the ability to derive anything useful about the password from the exchange, which is a good thing.

The mechanics, keeping it honest but brief. Your password is first converted into a **Password Element (PWE)**, a point on an elliptic curve. (Originally via “Hunting and Pecking”; after the Dragonblood attacks the industry moved to **Hash-to-Element / H2E**, which is now mandatory on 6 GHz.) Then both sides do a two-step dance *before* anyone is an authenticator or supplicant, because in SAE they’re equals: (hence the name SAE)

<table style="min-width: 75px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p>Step</p></td><td colspan="1" rowspan="1"><p>Direction</p></td><td colspan="1" rowspan="1"><p>Carries</p></td></tr><tr><td colspan="1" rowspan="1"><p>Commit</p></td><td colspan="1" rowspan="1"><p>both ways</p></td><td colspan="1" rowspan="1"><p>a scalar + a curve element (derived from the password + randoms)</p></td></tr><tr><td colspan="1" rowspan="1"><p>Confirm</p></td><td colspan="1" rowspan="1"><p>both ways</p></td><td colspan="1" rowspan="1"><p>a hash proving each side computed the same shared secret</p></td></tr></tbody></table>

Each side mixes its own random values with the PWE to build the Commit. They exchange Commits, each computes a shared secret, and then the Confirm proves they landed on the same secret, which can only happen if both started from the **same password**. Only then is a PMK derived and the familiar 4-way handshake runs on top.

![](https://cdn.hashnode.com/uploads/covers/6a1aa4222365cdee7fc9b999/e39b7a3c-a25d-4106-af15-8285131c6bdc.png align="center")

Now feel the problem. To even *participate* in SAE, the AP has to build its own Commit, and to build it, it needs the PWE, and to get the PWE, **it needs to already know your password.** But on a PPSK network it doesn’t know which of its hundred passwords is yours. There’s no username in the Commit. And unlike WPA2, it can’t just watch the exchange and reverse out the answer afterward, that offline-guessing resistance is the entire point of SAE.

Could it brute-force it, the way it trial-matched MICs in WPA2? In theory yes. In practice, no. Every candidate password means deriving a fresh PWE (elliptic-curve work, far heavier than PBKDF2) and running a full SAE attempt, and the client only ever completes the exchange for the *one* password it used. The elegant “try every key against one captured frame” move from WPA2 simply doesn’t exist. The protocol was built to make sure of it.

So the very thing that makes WPA3 stronger, no offline guessing, no password contribution leaking into the key, is precisely what makes vanilla PPSK impossible. It’s not a bug or a missing feature. It’s the security model working as designed.

## So how are vendors getting around it?

Nobody wants to tell their multi-tenant and IoT customers “sorry, no per-user keys on WPA3.” So the industry stopped trying to be clever inside the handshake and moved the lookup outside it. At the time of this writing I believe there are three patterns emerging:

•     **RADIUS-backed PSK.** The AP runs real WPA3-SAE, but before the exchange it asks a RADIUS server what the password is for this MAC address, then runs SAE with that. Juniper Mist's Access Assurance works this way, and Cisco's iPSK has long leaned on a RADIUS MAC-to-PSK lookup. It works, but you've now bolted a RADIUS dependency onto what used to be a self-contained Personal network.

You've also made the MAC address the identity, and that ages badly. Phones randomise their MAC now, and rotating addresses (iOS 18 and friends) are spreading. The moment a device's MAC changes, the lookup misses and the user drops off the network. An MDM profile can pin the address down, but you only have MDM on devices you own. In a hotel, a stadium, or any public venue you don't, which is exactly where per-user keys were supposed to shine. Classic WPA2 PPSK never looked at the MAC at all, so it never had this problem in the first place.

•     **SAE Password Identifiers.** The standard actually allows the client to include an identifier in the Commit so the AP knows which password to use. Clean on paper. The catch is client support, almost nothing in the wild lets a normal user type one, so it stays niche.

•     **Vendor extensions.** Fortinet supports MPSK over WPA3-SAE and SAE-Transition (transition mode stays on 2.4/5 GHz). Ruckus goes further with DPSK3 (Dynamic SAE), genuinely per-device keys on WPA3 with no RADIUS, even on 6 GHz, by provisioning each device through an onboarding step instead of trial-matching. Useful, but it's patented, proprietary territory, exactly what standardized PSK was supposed to get us out of.

And this is where it stops being academic. **6 GHz is WPA3-only by mandate**, no WPA2 allowed and H2E required. So the moment a customer wants PPSK on 6 GHz they hit this wall head-on, and every way around it costs something. RADIUS-backed lookups drag in a server and pin identity to a MAC address that modern phones increasingly randomise. The MAC-bound and transition-mode options either make you pre-register devices or quietly keep WPA2 alive on the lower bands.

And the one approach that does per-user keys on pure WPA3 without RADIUS, Ruckus DPSK3, is patented and vendor-locked. On Extreme specifically, PPSK isn't available on 6 GHz today (I expect it will be in the future) for the reason above, so for now per-user keys stay on 2.4 and 5 GHz with WPA2. The same is broadly true across vendors unless you accept one of those trade-offs.

## A look at the future

What I think is that the clean, self-contained PPSK we know, one SSID, a keystore, and a handshake clever enough to sort users by itself, is a WPA2-era artifact. It worked *because* WPA2 was a little too honest about the password. WPA3 closed that door on purpose, and it isn’t reopening.

Per-user keys aren't going away, they're just moving up the stack. My bet is that the future of "everyone gets their own credential" on WPA3 will look like a RADIUS lookup keyed on MAC or, more likely, some identifier, which starts to feel a lot like a lightweight 802.1X. And once you've got RADIUS in the picture anyway, the harder question becomes whether per-user PSK is even the right tool, or whether Passpoint / OpenRoaming and proper 802.1X are where multi-user onboarding actually wants to live. (I clearly have opinions, see my OpenRoaming post.)

For now, the practical advice is simple. If you need PPSK, you're living on 2.4 and 5 GHz with WPA2, and your 6 GHz plan is one of the workarounds above, a separate non-PPSK SSID just for 6 GHz, or a different onboarding model entirely. Know which one your vendor actually supports before you promise anything to a customer.

And as always, the fastest way to understand any of this isn’t the spec, it’s a capture. Put a client on the air, filter on `eapol` and the SAE Authentication frames, and watch a protocol tell you its secrets. WPA2 tells you a few too many. WPA3 has learned to keep its mouth shut ;-).

The pictures need some context, so I have written this below the blog to keep the reading a bit more clean:

**1) The WPA2 handshake (Wireshark).** The top pane lists a full join: probe, open authentication, association, then the four EAPOL “Key” messages M1–M4. M2 is selected. The highlighted WPA Key Nonce is the client’s SNonce, and the WPA Key MIC is its signature over the frame. That MIC is exactly what the AP recomputes against every key in its database to work out which user you are.

**2) The Client 360 view (ExtremeCloud IQ).** The cloud’s record of one client. The boxed panel ties the client’s MAC address to its PPSK user (**testuser-a685d1**), its user profile, SSID and VLAN. This is the “right identity came out” half of the handshake in the previous capture.

**3) The show auth output (AP CLI).** The AP’s own view of the same SSID. The top highlight is the StageNet config line: PPSK enabled, WPA2-AES-PSK, keys resolved against an external (cloud) server. The bottom highlight is the connected station, with a PMK and PTK derived and State = done, i.e. the handshake finished on the AP. The empty User-Name table underneath is the point: the AP did the crypto, but the human name lives in the cloud.

**4) The SAE exchange (Wireshark).** WPA3’s handshake. The selected Authentication frame is a Commit; the highlights are the Scalar and Finite Field Element (the curve element each side sends) and the status code showing Hash-to-Element (H2E). Notice what is missing: there is no MIC anywhere, nothing an AP or Controller could trial-match against. That single absence is why PPSK does not survive the move to WPA3.

# Appendix

## Abbreviations

**ANonce / SNonce**     Authenticator / Supplicant Nonce. Random numbers from the AP (M1) and the client (M2) that feed the PTK.  
**AP** Access Point. The radio clients connect to; in 802.11 it plays the role of the authenticator.  
**CWP** Captive Web Portal. The onboarding / sign-up page on the open registration SSID.  
**EAPOL**  Extensible Authentication Protocol over LAN. The frame type that carries the WPA2 4-way handshake.  
**GTK**   Group Temporal Key. The shared key for broadcast/multicast traffic, delivered in M3.  
**H2E**  Hash-to-Element. The modern way to derive the PWE (replaces “Hunting and Pecking”); mandatory on 6 GHz.  
**KCK** Key Confirmation Key. The slice of the PTK used to sign and verify handshake frames.  
**MIC** Message Integrity Check. The signature on a handshake frame; only comes out right if the correct PMK (password) was used. The field the controller trial-matches in PPSK.  
**PAKE** Password-Authenticated Key Exchange. The class of protocol SAE belongs to: it proves both sides know the password without leaking anything an eavesdropper could test.  
**PBKDF2** Password-Based Key Derivation Function 2. The function that stretches the passphrase into the PMK.  
**PMK** Pairwise Master Key. The 256-bit key derived from your passphrase plus the SSID; the root of all session keys.  
**PPSK** Private Pre-Shared Key. A unique Wi-Fi password per user (or device) on one shared SSID. Other vendors’ names: iPSK (Cisco), MPSK (Aruba, Fortinet, Mist), DPSK (Ruckus).  
**PSK** Pre-Shared Key. The classic single shared Wi-Fi password (WPA2-Personal).  
**PTK** Pairwise Transient Key. The per-session keys derived during the handshake from the PMK and both nonces.  
**PWE** Password Element. The password mapped onto a point on an elliptic curve; the seed of the SAE exchange.  
**RADIUS** Remote Authentication Dial-In User Service. The external auth/lookup server the WPA3 per-user workarounds lean on.  
**SAE** Simultaneous Authentication of Equals. WPA3-Personal’s handshake (codename “Dragonfly”).  
**SSID** Service Set Identifier. The network name you see and join.
