- From: Emil Lundberg <emil@yubico.com>
- Date: Thu, 29 Jan 2026 12:12:18 +0100
- To: Jori Lehtinen <lehtinenjori03@gmail.com>
- Cc: public-webauthn@w3.org
- Message-ID: <CANMnvkxis8te2oTirWLocD8G+LQJ-4rLp9gvc83GunXpDvzDLQ@mail.gmail.com>
Hi! I skimmed some of the sources, and it looks pretty straightforwardly in line with intended use cases for the PRF extension. I will caution against using constants as PRF inputs, for two reasons: 1) it's one less piece of data a would-be attacker would need to acquire in order to get hold of your base keys. With only seconds of physical access to your authenticator, the attacker can obtain your PRF outputs and then later use them to crack your wallet/vault/etc once they get hold of that. And 2) it's worth having the option to rotate the PRF inputs, should you ever need to in the future - for example if your base keys have been compromised and need to be replaced. I would suggest instead generating random PRF inputs and storing them in cleartext in the encryption envelope (or even better, any inputs not needed for decryption can of course be stored inside the ciphertext, if you're okay with an additional PRF call to produce their outputs) - that way any attacker at least has to obtain the encryption envelope *before* obtaining access to the authenticator. Also, be aware that your deriveHMACKey and deriveCipherKey functions don't really "derive" keys from the inputs, rather they just import the input verbatim as a key. This shouldn't make *much* difference since their input are already high-entropy, but you should be aware that the naming implies more than the implementation delivers. In particular, calling both functions with the same input would result in the same key for both uses. I would also recommend that your fromPRF function use a proper KDF, for example HKDF, to derive keys from the PRF outputs, rather than just applying SHA-256 once. Again this shouldn't make any difference in terms of output entropy, but it's good security hygiene. As far as I know, HMAC (and thus HKDF which is built upon it) is said to mitigate the severity of weaknesses in the hash function. Good luck with the project! Emil Lundberg Staff Engineer | Yubico <http://www.yubico.com/> Den ons 28 jan. 2026 kl 17:50 skrev Jori Lehtinen <lehtinenjori03@gmail.com >: > Hi! > > I’m working on an open-source, self-deployable coordination layer for > sovereign frontends: > https://github.com/z-base > > The key capabilities I’m trying to enable are: > > - > > Fully offline-capable encrypted state reconstruction > - > > Semantically blind support server (“base station”) > - > > State recovery and accessibility across devices (via cross-platform > credentials) > > I’m currently using navigator.credentials / WebAuthn as the key depency > for this: > https://www.npmjs.com/package/@z-base/zero-knowledge-credentials > > Here is the source code of the class interacting with > navigator.credentials > > https://github.com/z-base/zero-knowledge-credentials/blob/master/src/ZKCredentials/class.ts > > For additional context, here’s a draft spec that conceptualizes the > architecture (emphasis on: draft): > https://github.com/z-base/z-base/blob/main/docs/specifications/CONCEPT.md > > Is there any reason I shouldn’t use navigator.credentials for this? This > isn’t “standard” usage, but it’s also not trying to be. It’s using the API > in an innovative way to solve a very specific problem. > > I wanted to run this by you before I build a full-fledged system around it > and later discover that support for something like this won’t remain. > > To emphasize: I’m intentionally not using this for identity. The goal is a > fully private, offline-capable, but backed-up and realtime-capable user > space, within which users might control a published DID or similar. > > Regards, > Jori Lehtinen >
Received on Thursday, 29 January 2026 11:12:39 UTC