Storing Passkeys as a Single String and a Draft Go 1.28 crypto/passkey API

Filippo Valsorda proposes a PHC‑style one‑line Passkey record format that reuses WebAuthn authenticator data, eliminates the need for cross‑account Credential ID uniqueness checks, and includes a draft stateless crypto/passkey Go 1.28 API detailing registration and login flows.

TonyBai
TonyBai
TonyBai
Storing Passkeys as a Single String and a Draft Go 1.28 crypto/passkey API

Passkeys prevent phishing at the protocol level, but server‑side integration is considerably more complex than traditional password hashing.

Inconsistent storage recommendations

Google suggests using the Credential ID as the primary key together with public_key, backed_up and transports. Adam Langley, in his "Tour of WebAuthn", recommends a primary key of cred_id split into separate public_key_spki and backed_up columns. The lack of a unified schema leads to incompatibility across applications and languages.

Passkey‑record specification

Filippo Valsorda drafted the passkey‑record spec (c2sp.org/passkey-record), borrowing the Password Hashing Competition (PHC) string syntax to compress a Passkey credential into a single opaque line for database storage. The format reuses the existing WebAuthn authenticator data CBOR encoding and adds a transports parameter as a PHC field.

$webauthn$v=1$transports=hybrid+internal$<base64 authenticator data>

The only additional field beyond the authenticator data is transports, which lists supported transport methods (e.g., hybrid, internal). Applications therefore only need to maintain the association between a user account and its passkey record; all other metadata is handled elsewhere, with the sole exception of a separate backed_up flag that must be stored and updated independently.

Draft Go crypto/passkey API (proposed for Go 1.28)

Based on the passkey‑record format, Valsorda drafted a stateless crypto/passkey package. The API defines complete registration and login flows.

Registration flow

Call RelyingParty.NewRegistration with the logged‑in user and any existing passkey records.

Pass the returned JSON to parseCreationOptionsFromJSON() and then to navigator.credentials.create().

Send the browser‑generated PublicKeyCredential JSON to RelyingParty.Register.

Store the resulting passkey record in the database.

Login flow

Generate a login request with RelyingParty.NewLogin.

Store the request (keyed by RequestID(request)) in a short‑TTL cache and pass the JSON to parseRequestOptionsFromJSON(), then to navigator.credentials.get().

Feed the returned PublicKeyCredential JSON to Inspect, retrieve the cached request and the user’s passkey record from the database.

Pass the credential, request, and passkey record to RelyingParty.Login.

From these flows, the application’s responsibilities reduce to three tasks:

Maintain a stable, privacy‑preserving user ID.

Store the user’s passkey record.

Cache the challenge generated by RelyingParty.NewLogin.

Counter‑intuitive security insight

WebAuthn recommends servers SHOULD enforce uniqueness of Credential IDs across accounts to prevent collision attacks. Valsorda argues that if no Credential ID index exists, such attacks are impossible; the server simply looks up the passkey record using the user ID supplied in the login request. Consequently, the primary key should never be the Credential ID.

Do not let an attacker decide your PRIMARY KEY, and you will avoid PRIMARY KEY collision attacks.

References

Original article: https://words.filippo.io/passkey-record/

Spec draft: https://github.com/C2SP/C2SP/blob/push-oxkkyrwpqxot/passkey-record.md

Go API draft: https://godoc-play.exe.xyz/chibklhpf6nn

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

GoSecurityAPI designcryptoWebAuthnPasskeyPHC string
TonyBai
Written by

TonyBai

Tony Bai's tech world (tonybai.com). Not satisfied with just "knowing how", we strive for mastery. Focused on Go language internals, high-quality engineering practices, and cloud‑native architecture, exploring cutting‑edge intersections of Go and AI. Gophers who pursue technology are welcome—follow me and evolve with Go.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.