Home / Replicate / The passkey lab

A lab: the passkey opens the vault

The passkey lab

Each step of the design, as a thing you can press in your own browser: a passkey, its PRF bytes, the door derived from them, a recovery code, and the door created on a vault server.

A lab, not a feature. Nothing here changes your reading account, your balance or your personas. The page stores one public thing in this browser, the id of a passkey it made, so it can say so next time. Keys it derives are shown behind a reveal and kept in the page’s memory only; an access key you paste is kept the same way and forgotten when the page closes. The page loads no code from anywhere else, and every call it makes to a vault server is listed as it happens.

The design is in The passkey opens the vault: a passkey, through the WebAuthn PRF extension, gives the browser 32 bytes that only your authenticator can produce for this site; from those bytes the browser computes the key and the address of a small door vault, so nothing has to be stored to be found; the door holds the master vault’s key. Each card below is one step of that, as a thing you can press.

0. What this browser can do

WebAuthn, the platform authenticator, and whether the browser says it supports the PRF extension. Nothing to press: it is read when the page opens.

1. Make a passkey for this site

navigator.credentials.create() with rp.id set to this host, a resident key, user verification required, and the prf extension. The passkey is stored by your provider (Google Password Manager, iCloud Keychain, Windows Hello, a hardware key, or the browser’s own store); the page learns a credential id, a public key and whether PRF is on. It never learns who you are.

You will be asked for a touch, a face or a PIN.

2. Touch it: the PRF bytes

navigator.credentials.get() with the fixed input, the SHA-256 of a public string. The authenticator returns 32 bytes computed from a secret it keeps for this site and this passkey. The same passkey gives the same bytes on every device it syncs to, through the same kind of path; that is the whole trick. Through a different path (a phone over QR, instead of the provider on the device) the same passkey can give different bytes, which a test here found on 12 October 2026; the result shows which path answered, and the design gives each path its own door: one door per passkey path.

3. From the bytes, the door

The article’s derivation, made exact: HKDF to a seed, a passphrase and an 8-character vault id; then sgit’s own derivation of the read key and the write key, PBKDF2-HMAC-SHA256 at 600,000 iterations each, timed on this device. The door’s key is not stored anywhere: it comes out the same every time.

Runs by itself after 2.

4. A recovery code: the second door

26 characters of base32, 128 bits, made by the page and in the real flow shown once. In place of the PRF bytes it derives a second door to the same master, for the day every passkey is gone.

Type a code back:

5. Test vectors: the browser and sgit agree

The same derivation from a fixed, fake PRF output, compared value by value with what sgit’s own Python produced (vectors.json, from admin/build/passkey_vectors.py). Runs when the page opens. If any line is wrong, the browser and the command line would open different vaults.

What this lab is, and is not

For an agent

A lab page for the design in https://newsroom.sgit.ai/articles/the-passkey-opens-the-vault.html: in a browser, make a passkey with the PRF extension, get the PRF bytes, derive a door vault's passphrase and id (HKDF) and sgit's read and write keys (PBKDF2, 600,000 iterations), make a recovery code, compare with sgit's Python at https://newsroom.sgit.ai/passkey/vectors.json, and with an access key create the door on a vault server and open it. It stores nothing but a passkey id; it does not touch the reading account. The derivation is written out at the top of https://newsroom.sgit.ai/passkey/lab.js.