Bringing Anonymous Attestation to Existing Hardware

WebAuthn attestation serves an important purpose: it lets a server confirm that a security key is genuine and was produced by a trusted manufacturer. In controlled settings, like a corporate network or a bank, this works well because the server already has a relationship with the user, and learning the key's manufacturer adds little privacy exposure. But in an open setting, such as Cloudflare's Cryptographic Attestation of Personhood, that same attestation leaks the make and model of the hardware key — a detail that, when combined with other signals like user agent or time of day, starts to resemble a fingerprint.

Browsers therefore show users a prompt when a website requests attestation, to make them aware that identifying information is being transmitted. The attestation itself is a digital signature produced with a key stored in the hardware's secure enclave, alongside a certificate chain that traces back to the manufacturer. This allows any server to verify authenticity, but it also reveals significantly more than is necessary. For proof of personhood, the only thing Cloudflare actually needs to establish is a single bit: the user possesses a legitimate, trustworthy hardware security key — not which company built it or which model it is.

The immediate problem is that existing attestation infrastructure was built with vendor-based trust in mind. In environments like financial institutions, only a handful of manufacturers are deemed acceptable, and revealing the vendor is a feature rather than a bug. In an open-vendor design, no manufacturer should be privileged, but all genuine keys should be accepted. Trustworthiness is determined by the FIDO MetaData Service, which maintains root certificates for registered manufacturers and tracks compromised keys. Cloudflare already scripts updates to import these roots, so its software always reflects the current trust list, adjusting as new vendors are added or old ones are compromised.

The FIDO consortium does enforce a privacy baseline: each attestation key must be shared by at least 100,000 devices, which sets a lower bound on the anonymity set. That helps ensure that no single key can be used to trace individual devices. Yet not all manufacturers reach that volume, and users shouldn't have to choose the largest vendors to get basic privacy. While Cloudflare has strict policies about handling this data, policies aren't the same as not possessing the data. Even with FIDO's constraints, attestation exposes a user's hardware vendor, and Cloudflare would rather not know that at all.

Anonymous Credentials Without New Hardware

The core requirement is to verify that a responding device is a real security key — not a software emulator controlled by a bot — without learning anything else about the credential. This is the general problem of anonymous credentials, which has been studied for decades, with various proposed and deployed solutions. Those schemes, however, typically require that the credential attestation logic was designed with that particular scheme in mind from the start. Asking every hardware manufacturer to add new capabilities in the next few months is unrealistic, and replacing the world's existing pool of security keys is out of the question. Any practical solution must work with the hardware that already exists in the field.

That constraint sounds like it makes the problem impossible. Proving knowledge of something without revealing what that something is seems contradictory. But a simple analogy shows it is often doable: claiming to own a mailbox key can be demonstrated by asking the verifier to place a letter inside and then retrieve it; claiming to know a phone number can be verified by asking the number's owner to receive a call. These are examples of zero-knowledge proofs, abbreviated ZKP — methods by which one party proves possession of a secret without disclosing it.

A classic illustrative example is the Where's Waldo game. Pointing at Waldo on the page immediately tells the verifier everything. Instead, a prover could place a large sheet of paper over the illustration with a hole just big enough to expose Waldo's face. The verifier sees that the prover knows where Waldo is, but gains no information about his true location on the page.

Zero-knowledge proofs become practically useful when they can be composed. The enabling mechanism is a commitment — a cryptographic envelope that locks in a value at a particular moment, which can be opened later to reveal that value. Commitments prevent tampering; they are like a magician's sealed envelope or a silent auction bid that cannot be altered once submitted. These schemes also solve the problem of fair coin flipping between two parties who don't trust each other: Alice and Bob each flip a coin and exchange commitments to their results before revealing them. Because commitments are exchanged before anyone can open them and see the other's result, neither party can fake an outcome based on the final result — the opening phase will reveal any mismatch immediately.

Commitments serve as the glue for building complex zero-knowledge statements from simpler ones. If a proof establishes that some property holds for a committed value, and another proof demonstrates a different property of the same commitment, the combination proves that both properties hold simultaneously for that single underlying value. This allows chains of reasoning: proving one commitment is the sum of values in two others, or proving a committed value appears in a known list. With basic gates like "this commitment is one if and only if these other commitments are both one" and "this commitment is one if either of two other commitments is one," any logical statement can be expressed. Generic techniques exist to convert an arbitrary statement into a zero-knowledge proof, though the result is slow and complex unless carefully optimized.

Turning ECDSA Attestations into Zero-Knowledge Proofs

In Cryptographic Attestation of Personhood, the server challenges the browser to produce a signature from its hardware security key. That signature proves the key is genuine. With our zero-knowledge approach, the browser does not send the signature itself. Instead, it sends a proof that a key from a server-provided list generated the signature. The server learns only that a valid attestation exists — never which key produced it.

We evaluated several proof systems, including SNARKs. Their code size, toolchain requirements, and proving complexity made them impractical here. SNARKs also rest on more complicated security assumptions than the scheme we ultimately selected. This remains an active research area, and today's best choice may not be tomorrow's.

The attestations from the hardware keys we support use ECDSA. The scheme bears structural similarities to many zero-knowledge proofs. The signer computes a point R = kG for a random value k, takes r as the x-coordinate of R, and combines their private key with the message hash to produce s. The pair (r, s) is the signature, and the verifier recomputes R from these values and the public key.

Directly proving the standard ECDSA verification equation in zero knowledge is expensive: it requires conversions between value representations that carry heavy proof overhead. We bypass this by having the prover send R directly and commit to a value z derived from r and s. This simplification makes the verification equation tractable in a proof system. Anyone can convert between a standard ECDSA signature and our tweaked form without any secret information, so the security level is unchanged.

The overall statement splits naturally into two parts: the message was signed by a key, and that key appears on the list. The prover first demonstrates that a key inside a commitment signed the message. Then they prove the committed key is on the list. The verifier checks both components independently.

The signature verification proof requires a zero-knowledge argument that one elliptic curve point is a known power of another. This is comparatively straightforward, though it internally needs sub-protocols for correct point addition and field arithmetic. This step dominates proof generation and verification time. Once it verifies, the verifier accepts that the committed public key produced the signature.

For the list membership proof, we use the construction by Groth and Kohlweiss. The prover commits to the binary expansion of their key's position in the list, proves that expansion consists of bits, and supplies auxiliary information. Both parties then evaluate polynomials that vanish exactly when the commitment corresponds to a list entry. The implementation is surprisingly compact for the complexity of the task.

By evaluating a polynomial, we show our committed value is a zero.

The verifier confirms the Groth-Kohlweiss proof and then checks that the signed message is the expected one. The efficiency scales well with list size: each additional list element costs just one multiplication. If every check passes, we know the signature came from a sufficiently secure hardware key — and nothing else about it. Any failure indicates a problem.

Finding a Curve with the Right Shape

Our statements about ECDSA became statements about points on the P-256 curve and ultimately about arithmetic in its base field. Proving such statements is easiest when a group's order matches the field size, so we needed an elliptic curve with a very specific number of points. This reverses the usual cryptographic workflow, which starts with a convenient base field and searches for a curve of prime or nearly prime order.

The curve we needed is determined by number-theoretic constraints, and finding it required classical machinery.

Elliptic Curves as Tori

Over the complex numbers, every elliptic curve is isomorphic to a torus. The geometry is encoded by a rectangle whose opposite sides are glued, and folding the entire complex plane along this pattern produces a lattice. The shape of the torus — how fat or thin it is in each direction — is captured by a parameter we can always normalize so one lattice generator is 1.

BLOG-499 Embedded Image - HnZiDl
BLOG-499 Embedded Image - KIEbGY

Addition of complex numbers becomes addition on the torus, analogous to integer addition modulo 2. The analytic picture connects to algebra through the Weierstrass function and its derivative, which generate the ring of complex-valued functions on the lattice and satisfy an equation of the form y² = x³ + ax + b. The classical algebraic addition formulas emerge from this relationship. The j invariant is a more arithmetic-friendly encoding of the lattice shape than the raw parameter, since different parameters producing the same lattice yield the same j.

Complex Multiplication and Its Arithmetic

Most elliptic curves admit only multiplication by integers as endomorphisms. Some have extra ones. The lattice {1, i}, for example, is invariant under multiplication by i, and the corresponding curve y² = x³ + x has an endomorphism sending x to -x and y to iy. This is called complex multiplication, and it only occurs when the multiplier satisfies a quadratic equation.

Each such lattice is associated with a discriminant — the discriminant of that quadratic field. The elliptic curves with complex multiplication by a given discriminant correspond exactly to classes of binary quadratic forms with that discriminant, a connection that traces back to Gauss's work on composition laws. Three seemingly different questions — about curve counts, quadratic form classes, and ideal arithmetic in quadratic fields — all share the same answer.

Over a prime field, every elliptic curve gains the Frobenius endomorphism, which sends x to xᵖ and y to yᵖ. This endomorphism satisfies a quadratic equation whose linear term relates directly to the curve's point count. Unless a curve is supersingular — extremely rare — it has only one extra endomorphism. If the curve has complex multiplication, that endomorphism must be Frobenius, and the point count is forced.

We can therefore search for a curve with a prescribed order by finding integer solutions to t² + Dy² = 4N for small D, testing whether p = N - t + 1 is prime, and then factoring the Hilbert class polynomial of D modulo p. A root of that polynomial gives the j invariant, and a quadratic twist may be needed to fix the sign of t. This process yields exactly the curve we need for efficient proofs over P-256's base field. The full procedure runs in minutes and produces the curve with the required order.

Performance and What the Server Actually Sees

The engineering effort to optimize the proof pipeline has paid off. Generating a proof now takes a few seconds, while verification completes in a few hundred milliseconds. That level of performance is practical for real-world use, meaning websites can verify the security of security keys without imposing a noticeable delay or forcing users to sacrifice privacy.

BLOG-499 Embedded Image - NP6m48

The crucial property of this system is that the verifying website learns only one thing: whether the attestation key used to generate the signature appears on the list the website provided. This stands in sharp contrast to direct WebAuthn usage, where the server can extract more granular identifying information—particularly if a manufacturer has defined a batch size that is too small. Rather than relying on a policy to protect user privacy after the fact, this approach removes the sensitive information from the attestation flow entirely.

From Demonstration to Community Standard

This prototype proves that a zero-knowledge proof can serve as a working privacy enhancement for WebAuthn attestation. The immediate next steps are internal: improving performance further and hardening security features. However, the larger goal is to evolve this into a privacy-preserving WebAuthn extension that ships in every browser, ensuring users’ data never leaves their devices in the first place.

The current work is a proof of concept that demonstrates a fundamental principle: zero-knowledge proofs can reframe WebAuthn attestation so that all manufacturers are treated identically by design, user privacy is preserved by construction, and the mechanism remains usable by any website. The privacy concerns that arise from large-scale deployment of attestation are not insurmountable.

A production-ready system requires more than just sound cryptography. Key integration work remains:

  • Browser-level integration so users do not encounter warnings about the information the zero-knowledge proof intentionally discards.
  • A safe onboarding path for users whose devices are not yet on the trusted list, allowing them to submit their key for review without undermining the list’s integrity.
  • Guardrails to prevent the trusted list itself from being used as a tool to pinpoint individual keys.
  • Server-side protections: verification is more compute-intensive than traditional methods, so implementations will need rate limiting and similar abuse mitigation.

SNARKs would offer meaningful efficiency gains for verification, though they would increase the code footprint of the demonstration. Ultimately, bringing these changes into the core web platform requires collaboration with users, browser vendors, and other stakeholders. The team is inviting direct feedback and contributions at [email protected].

The goal for this line of research aligns with the broader mission behind the Cryptographic Attestation of Personhood: to give users a more private and convenient way to prove their humanity than what CAPTCHA providers offer. Unsatisfied with the privacy trade-offs baked into existing attestation flows, the team has shown that advanced cryptography can materially improve the privacy guarantees of a real-world protocol used across the web.