for agents/llms.txtv0.9.3

Home / Articles / The passkey opens the vault: touch a passkey, and a master vault for every user, with no server of ours, no account and no email

The passkey opens the vault: touch a passkey, and a master vault for every user, with no server of ours, no account and no email

By · 2026-10-11 · article v1.2.0, 3 versions · sgit.ai v0.7.55 · passkeyswebauthnprfvaultskey-managementgoogle-sign-inclient-sidenewsroomarchitecturebriefsecretsarticle

Abstract: The missing piece of the client-side puzzle is a user who can open their own vaults on any device, in a few seconds, with nothing to remember and nothing to sign up for. This is the design. A passkey, through the WebAuthn PRF extension, gives the browser 32 bytes that only your authenticator can produce for this site, and from those bytes the browser computes the key of a small door vault, which holds the key of your master vault, which holds the keys of everything else, starting with your newsroom vault. There is no sign-in: the page makes and uses the passkey through the browser's own API, with no Google app, no OAuth and no server, and it never learns your email or your name. The question I could not answer, where the encrypted vault key is stored, has a simple answer: nowhere. sgit vault keys are made in the client, so the door's key and its id can be computed from the passkey on any device, before anything is fetched, and there is no chicken and egg. A recovery code makes a second door to the same master. PRF is now supported by Google Password Manager, iCloud Keychain, Windows Hello and Firefox. The unlock costs up to six key derivations, measured. The first part is the technical design and the brief for the MVP on newsroom.sgit.ai, end to end; the second is what it enables: accounts with no server and no identity, for this site and for any other.

The key chain. The passkey's PRF output derives a door vault, the door holds the master vault's key, and the master holds the keys of everything else. Nothing secret is stored anywhere to be fetched, and the vault server sees ciphertext at every step.

This is the missing piece of the puzzle. In I miss it, so it is working I described the feature I miss: the newsroom on every device, in sync, through my own encrypted vault. In No server, by design I listed identity as one of the last things that still seemed to need a server. This article joins the two, in detail.

The experience I want is simple. I open newsroom.sgit.ai in a new browser. I am asked to touch my passkey. And my reading account opens, the same as on every other device, because it is now in a vault only I can open. Two steps, one of them a gesture, no server of ours anywhere, and nothing to sign up for.

I had one question I could not answer: where is the vault key kept? The short answer, after the research, is that it is not kept anywhere. It is computed. The rest of this article is why that works, the design end to end, and what it makes possible for every other site we run.

In short

Part one: the design

What each piece actually gives you

It helps to separate the pieces, because they are easy to blur.

PieceWhat it gives the pageWhat it does not give
Sign in with Google (later, optional, on its own origin)Continuity: a stable account id for support, a Drive backup, a reference for purchasesAny key. It is not in the MVP and not needed to open anything
A passkey for this siteA gesture (touch, face, PIN), a signature, and with PRF, 32 bytes computed from a secret the authenticator keeps for this site and this passkeyThe bytes to anyone but the page on this site that asked, after the gesture
The passkey providerSync: Google Password Manager across your Chrome and Android devices, iCloud Keychain across your Apple devices, or none (a hardware key)Anything about what the bytes are for
sgitVault keys made in the client (a 24-character passphrase and an 8-character vault id), read and write keys derived from them, ciphertext on the serverA way to find a vault you have no key for
The access keyThe right to create vaults and write to them on the vault server, the thing people will buyAny way to read a vault

One clarification that matters. What people call "the Google passkey" is a passkey for this site, registered by this page under this site's name, which your provider stores and syncs: Google Password Manager if you use Chrome, iCloud Keychain on Apple devices. It is not the passkey you use to sign in to Google, and a website cannot get PRF bytes from that one. There is no sign-in in this flow at all: the page registers a discoverable credential with a random user handle, and the only login involved is the one you already have with your passkey provider, which syncs it. The site learns a credential id, a public key and, after your gesture, 32 bytes. Not your email, not your name, not which account syncs it.

Where the vault key lives: nowhere

The places the key could live, and how you would find each before you could open it. Deriving the door from the passkey needs nothing to be found; the stored options become backups.

Every option for storing an encrypted vault key has the same problem: you have to find the encrypted key before you can open it, so it has to live somewhere you can reach with only what you have at that moment, which is your Google sign-in and your passkey.

And then the option that needs none of it. sgit vault keys are generated in the client: a random passphrase and a random vault id, and sgit init accepts a key it is given. So instead of generating a door vault's key at random and storing it, the browser computes it from the PRF bytes: the passphrase, and the vault id, with HKDF. On any device where the passkey is available, the same gesture gives the same bytes, the same door id and the same door key. The browser knows where to look and how to open it before it has fetched anything. The door holds one thing, the master vault's key, which is random and made once. The master holds everything else.

So the answer to my question: the vault key is not stored, it is derived; the master key is stored, inside a vault that only the passkey can find; and Google's app-data folder can keep a backup copy, encrypted, for the day something goes wrong.

The derivation

For the newsroom MVP, with the relying party ID newsroom.sgit.ai:

  1. The PRF input is a fixed, public value: SHA-256("newsroom.sgit.ai/door/v1"). An input is not a secret; only the authenticator can turn it into the 32 bytes.
  2. The door seed is HKDF-SHA256(ikm = PRF bytes, salt = SHA-256("newsroom.sgit.ai"), info = "sgit/door/v1").
  3. The door's passphrase and vault id are two more HKDF outputs from the seed. sgit accepts any printable ASCII passphrase up to 256 characters, so the passphrase is the hex of 32 bytes (info = ".../passphrase"), keeping all 256 bits. The vault id has to be lowercase letters and digits, 4 to 24 of them, so 8 characters are drawn from a third output (info = ".../id") with rejection sampling, so that no character is favoured.
  4. The door vault key is the sgit vault key made of those two, and from there, sgit's own derivation gives the read and write keys, exactly as the command line does: PBKDF2-HMAC-SHA256 at 600,000 iterations, once for the read key and once for the write key. That is the cost of this design. Door, master and newsroom vault need up to six derivations; measured in headless Chromium on a four-core machine, one takes about 105 ms and six run together about 640 ms, and a phone is several times slower, so a cold unlock can spend two to four seconds deriving keys before it fetches anything. The brief measures it on a phone, derives each vault's keys once per session, runs them in a worker, and derives a write key only when there is something to write.
  5. The recovery door is the same, with the recovery code in place of the PRF bytes: 26 characters of base32, 128 bits, made by the page and shown once. It is long so that it needs no password stretching, as in the secrets.sgit.ai keyring design.
  6. Collisions are not a practical worry with 36⁸ possible ids, but the page checks: a derived id that already holds something it cannot open is skipped, with a counter in the HKDF info.

The browser and the command line must agree byte for byte, so the brief includes test vectors: the same inputs through the browser code and through sgit in Python, with the same keys out.

What is in each vault

The flows

The first run, a new device, and adding a passkey or recovering. Every step runs in the browser, against the user's passkey provider for the gesture, and the vault server for ciphertext.

First run. Create a passkey for the site with prf enabled; if the authenticator cannot do PRF, the page says which kinds can and offers another. Touch it: the PRF bytes give the door. Generate the master key, the newsroom vault key, a key pair and a recovery code. Paste the access key. Create the door, the master, the newsroom vault and the recovery door. Move the reading account from the browser's storage into the newsroom vault. Show the recovery code once, behind "I have written it down".

A new device. Touch the passkey, synced to this device or used from a phone by QR. The PRF bytes give the same door, the door gives the master, the master gives the newsroom vault. Reading needs no access key; the access key comes out of the master, so this device can write as well. Merge this browser's reading into its own log.

A second provider. An iPhone with iCloud Keychain and a Windows laptop with Windows Hello have different passkeys. While unlocked on one, register the other: its PRF bytes make a second door to the same master.

Lost a passkey. Type the recovery code; it derives the recovery door; register a new passkey; retire the old door in the master's list.

Signing out and locking. Keys exist only in the page's memory: cleared on sign-out, after a period of inactivity, and when the page is closed. The browser's own copy of the reading account stays as it is today.

Security, said plainly

Where PRF works today

As of October 2026, from vendor documentation and published tests (see the sources):

Passkey providerPRF
Google Password Manager (Chrome, Edge and Samsung Internet; Android)Yes, by default; desktop Chrome from version 136
iCloud Keychain (Safari 18, macOS 15)Yes
Windows HelloYes, since the February 2026 update to Windows 11
FirefoxYes, on macOS from version 139 and Windows from version 148
Hardware security keysYes through hmac-secret, but not with YubiKeys in Safari
Chrome's own profile authenticatorNo

The page checks prf.enabled when it creates the passkey, and never guesses: if it is false, it says so and offers another authenticator or the recovery code.

What happens in a clean browser

The table above is about browsers. The question that matters to a reader is about devices: will the newsroom I opened on my laptop be the same one on my phone? That depends on where the passkey lives, which is a choice the reader made long before they met this site, usually without noticing.

Where a passkey can live, what each place needs, whether the passkey travels, whether it can return the PRF bytes, and what that means for the reader. The ladder below the table is what the page offers when PRF is off.
Where the passkey livesNeedsTravels?PRFWhat the reader gets
Google Password Manager (Chrome signed in, Android)A Google accountYes, to every device signed in to itYesThe same newsroom everywhere
iCloud Keychain (Safari, iPhone, iPad, Mac)An Apple IDYes, across Apple devicesYes, Safari 18 and macOS 15The same newsroom on every Apple device
Windows Hello (Windows 11)The device; a Microsoft account to syncDevice-bound, unless syncedYes, since February 2026This PC, or every PC on the account
A hardware key (YubiKey and others)The key, and its PINYes, wherever the key is plugged inYes, through hmac-secret; not with YubiKeys in SafariNo account anywhere; a few dozen passkeys per key
Your phone, by QR (the hybrid flow)A passkey on the phone, in its own providerYes, one scan at a timeWhere the phone's provider doesA clean laptop opens with the phone beside it
Chrome's own profile store (a clean Chrome, no provider)NothingNo: this browser, on this computerNo, in 2026 testsSigns, returns no bytes: the door cannot be derived

So the rule, in one line: the same newsroom on every device needs a synced provider or a hardware key in your pocket. A clean browser with neither gives you this device, plus the recovery code. A passkey made there still works, as a passkey; it is stored by the device, tied to that browser profile on that computer, and deleted with it. The catch for this design is the last row: Chrome's own store, used when there is no provider (a clean Chrome on Linux, or on a Mac with iCloud Keychain off), signs but returns no PRF bytes in 2026 tests, so the door cannot be derived there at all.

Two things follow. The page learns which case it is in at creation, from prf.enabled, and never guesses. And when PRF is off, it offers a ladder, in this order: sign in to a provider, so the passkey syncs from now on; use your phone by QR, one scan at a time; plug in a hardware key; or stay on this device, where the browser's own copy keeps working and the recovery code is the way back. That is a real limitation of PRF today, not of the design, and the article would be dishonest without it. One caveat on the Chrome-profile row: it comes from a vendor's published tests, so the brief includes a five-minute check on a clean profile before anyone depends on it.

The brief for the MVP

For the session that runs newsroom.sgit.ai. Written by the sgit.ai site session for Dinis Cruz, 11 October 2026. Dinis decides what ships, and is the first user.

  1. No sign-in. The first screen is the passkey. Google sign-in is a later phase, on its own origin, and only for what it is good for: continuity for support, a Drive backup, a reference for purchases.
  2. The passkey: create with rp.id = newsroom.sgit.ai, a resident key, user verification required, extensions.prf; get with the fixed PRF input; check prf.enabled. When it is false, the ladder: sign in to a provider, your phone by QR, a hardware key, or this device only with the recovery code, each explained in one line.
  3. The derivation in part one, with test vectors shared with the sgit command line.
  4. The vaults: door, master, newsroom and recovery door, created with the access key, using the browser code that already reads and writes vaults, taken from the vault web app and tools.sgraph.ai and vendored into the reader repository.
  5. The move: the reading account from the browser's storage into the newsroom vault, as the first device's log.
  6. The right-hand side: once open, show the vault: the master's list of vaults and doors, and the newsroom vault's contents, so the user can see what is kept and where.
  7. Tests: Chromium's virtual authenticator with PRF in the build (secrets.sgit.ai found it works in Chromium 141); the first run, a new device and the recovery code, end to end; a clean Chrome profile with no provider, to confirm what its own store returns for prf.enabled and that the ladder appears; two devices editing offline and agreeing; a synthetic reader who has never heard of a vault key.
  8. Not in the MVP: Google sign-in, the Drive backup, sharing across sites, anything on a server of ours.

The acceptance test is the experience in the second paragraph of this article: a new browser, a gesture, and my reading account, on my iPhone, my iPad, my laptops and my iMac.

Part two: what this enables

Once these dots are connected, we have something we did not have before: an end-to-end path from a login with a second factor to a vault, entirely in the browser, on commodity pieces. And just about every site and project we build needs exactly that.

This is why I think it matters more than a login feature. It is the moment the client-side pattern stops needing anyone's server for identity and storage, and becomes something other sites can use.

What this does not claim

If you build sites that need accounts without a back end, or you work on passkeys or password managers and want to try this with us, write to agent@riskmandate.ai.

Where this comes from

A voice memo of mine, recorded on 11 October 2026, asking for the design and for research into what a passkey gives a website and where an encrypted vault key could be kept; written by this site's agent in the voice of this site. The argument and the editorial responsibility are mine. The design builds on secrets.sgit.ai's published design (how it works, the keyring format, passkeys, WebAuthn and PRF and keys), and on how sgit generates and parses vault keys in the client (generate_vault_key and parse_vault_key in the sgit command line); the unlock cost was measured with WebCrypto PBKDF2 in headless Chromium on 11 October 2026. The research: Corbado, Passkeys and WebAuthn PRF for end-to-end encryption (2026) and WebAuthn L3 support in credential managers; Yubico, Developer's guide to PRF; Mozilla, support for the WebAuthn PRF extension; Chromium, intent to ship the PRF extension; web.dev, passkey reuse across sites with Related Origin Requests; Google, choosing Google Drive API scopes and authorising for the web. Related articles: I miss it, so it is working, No server, by design, Where the vault keys live, RFC 0001 and How to run synthetic users.

Threads

Vaults & methodSite & engineering This article as a graph →

Builds on

Continued by

All articles · All graphs

Article No. 77 · start a reading list with it

Want the next issue by email. One issue a week or so: what was published, what it adds up to, and what is worth your time. Subscribe to the SGit Newsroom →

← All articles