
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Tue, 14 Apr 2026 19:02:42 GMT</lastBuildDate>
        <item>
            <title><![CDATA[Anonymous credentials: rate-limiting bots and agents without compromising privacy]]></title>
            <link>https://blog.cloudflare.com/private-rate-limiting/</link>
            <pubDate>Thu, 30 Oct 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ As AI agents change how the Internet is used, they create a challenge for security. We explore how Anonymous Credentials can rate limit agent traffic and block abuse without tracking users or compromising their privacy. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>The way we interact with the Internet is changing. Not long ago, ordering a pizza meant visiting a website, clicking through menus, and entering your payment details. Soon, you might just <a href="https://www.cnet.com/tech/services-and-software/i-had-chatgpt-order-me-a-pizza-this-could-change-everything/"><u>ask your phone</u></a> to order a pizza that matches your preferences. A program on your device or on a remote server, which we call an <a href="https://developers.cloudflare.com/agents/concepts/what-are-agents/"><u>AI agent</u></a>, would visit the website and orchestrate the necessary steps on your behalf.</p><p>Of course, agents can do much more than order pizza. Soon we might use them to buy concert tickets, plan vacations, or even write, review, and merge pull requests. While some of these tasks will eventually run locally, for now, most are powered by massive AI models running in the biggest datacenters in the world. As agentic AI increases in popularity, we expect to see a large increase in traffic from these AI platforms and a corresponding drop in traffic from more conventional sources (like your phone).</p><p>This shift in traffic patterns has prompted us to assess how to keep our customers online and secure in the AI era. On one hand, the nature of requests are changing: Websites optimized for human visitors will have to cope with faster, and potentially greedier, agents. On the other hand, AI platforms may soon become a significant source of attacks, originating from malicious users of the platforms themselves.</p><p>Unfortunately, existing tools for managing such (mis)behavior are likely too coarse-grained to manage this transition. For example, <a href="https://blog.cloudflare.com/per-customer-bot-defenses/"><u>when Cloudflare detects that a request is part of a known attack pattern</u></a>, the best course of action often is to block all subsequent requests from the same source. When the source is an AI agent platform, this could mean inadvertently blocking all users of the same platform, even honest ones who just want to order pizza. We started addressing this problem <a href="https://blog.cloudflare.com/web-bot-auth/"><u>earlier this year</u></a>. But as agentic AI grows in popularity, we think the Internet will need more fine-grained mechanisms of managing agents without impacting honest users.</p><p>At the same time, we firmly believe that any such security mechanism must be designed with user privacy at its core. In this post, we'll describe how to use <b>anonymous credentials (AC)</b> to build these tools. Anonymous credentials help website operators to enforce a wide range of security policies, like rate-limiting users or blocking a specific malicious user, without ever having to identify any user or track them across requests.</p><p>Anonymous credentials are <a href="https://mailarchive.ietf.org/arch/msg/privacy-pass/--JXbGvkHnLq1iHQKJAnfn5eH9A/"><u>under development at IETF</u></a> in order to provide a standard that can work across websites, browsers, platforms. It's still in its early stages, but we believe this work will play a critical role in keeping the Internet secure and private in the AI era. We will be contributing to this process as we work towards real-world deployment. This is still early days. If you work in this space, we hope you will follow along and contribute as well.</p>
    <div>
      <h2>Let’s build a small agent</h2>
      <a href="#lets-build-a-small-agent">
        
      </a>
    </div>
    <p>To help us discuss how AI agents are affecting web servers, let’s build an agent ourselves. Our goal is to have an agent that can order a pizza from a nearby pizzeria. Without an agent, you would open your browser, figure out which pizzeria is nearby, view the menu and make selections, add any extras (double pepperoni), and proceed to checkout with your credit card. With an agent, it’s the same flow —except the agent is opening and orchestrating the browser on your behalf.</p><p>In the traditional flow, there’s a human all along the way, and each step has a clear intent: list all pizzerias within 3 Km of my current location; pick a pizza from the menu; enter my credit card; and so on. An agent, on the other hand, has to infer each of these actions from the prompt "order me a pizza."</p><p>In this section, we’ll build a simple program that takes a prompt and can make outgoing requests. Here’s an example of a simple <a href="https://workers.cloudflare.com/"><u>Worker</u></a> that takes a specific prompt and generates an answer accordingly. You can find the code on <a href="https://github.com/cloudflareresearch/mini-ai-agent-demo"><u>GitHub</u></a>:</p>
            <pre><code>export default {
   async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise&lt;Response&gt; {
       const out = await env.AI.run("@cf/meta/llama-3.1-8b-instruct-fp8", {
           prompt: `I'd like to order a pepperoni pizza with extra cheese.
                    Please deliver it to Cloudflare Austin office.
                    Price should not be more than $20.`,
       });


       return new Response(out.response);
   },
} satisfies ExportedHandler&lt;Env&gt;;</code></pre>
            <p>In this context, the LLM provides its best answer. It gives us a plan and instruction, but does not perform the action on our behalf. You and I are able to take a list of instructions and act upon it because we have agency and can affect the world. To allow our agent to interact with more of the world, we’re going to give it control over a web browser.</p><p>Cloudflare offers a <a href="https://developers.cloudflare.com/browser-rendering"><u>Browser Rendering</u></a> service that can bind directly into our Worker. Let’s do that. The following code uses <a href="https://www.stagehand.dev/"><u>Stagehand</u></a>, an automation framework that makes it simple to control the browser. We pass it an instance of Cloudflare remote browser, as well as a client for <a href="https://developers.cloudflare.com/workers-ai/"><u>Workers AI</u></a>.</p>
            <pre><code>import { Stagehand } from "@browserbasehq/stagehand";
import { endpointURLString } from "@cloudflare/playwright";
import { WorkersAIClient } from "./workersAIClient"; // wrapper to convert cloudflare AI


export default {
   async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise&lt;Response&gt; {
       const stagehand = new Stagehand({
           env: "LOCAL",
           localBrowserLaunchOptions: { cdpUrl: endpointURLString(env.BROWSER) },
           llmClient: new WorkersAIClient(env.AI),
           verbose: 1,
       });
       await stagehand.init();


       const page = stagehand.page;
       await page.goto("https://mini-ai-agent.cloudflareresearch.com/llm");


       const { extraction } = await page.extract("what are the pizza available on the menu?");
       return new Response(extraction);
   },
} satisfies ExportedHandler&lt;Env&gt;;</code></pre>
            <p>You can access that code for yourself on <a href="https://mini-ai-agent.cloudflareresearch.com/llm"><i><u>https://mini-ai-agent.cloudflareresearch.com/llm</u></i></a>. Here’s the response we got on October 10, 2025:</p>
            <pre><code>Margherita Classic: $12.99
Pepperoni Supreme: $14.99
Veggie Garden: $13.99
Meat Lovers: $16.99
Hawaiian Paradise: $15.49</code></pre>
            <p>Using the screenshot API of browser rendering, we can also inspect what the agent is doing. Here's how the browser renders the page in the example above:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6lXTePCTUORCyyOWNNcwZ8/5978abd1878f78107a2c9606c3a1ef51/image4.png" />
          </figure><p>Stagehand allows us to identify components on the page, such as <code>page.act(“Click on pepperoni pizza”)</code> and <code>page.act(“Click on Pay now”)</code>. This eases interaction between the developer and the browser.</p><p>To go further, and instruct the agent to perform the whole flow autonomously, we have to use the appropriately named <a href="https://docs.stagehand.dev/basics/agent"><u>agent</u></a> mode of Stagehand. This feature is not yet supported by Cloudflare Workers, but is provided below for completeness.</p>
            <pre><code>import { Stagehand } from "@browserbasehq/stagehand";
import { endpointURLString } from "@cloudflare/playwright";
import { WorkersAIClient } from "./workersAIClient";


export default {
   async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise&lt;Response&gt; {
       const stagehand = new Stagehand({
           env: "LOCAL",
           localBrowserLaunchOptions: { cdpUrl: endpointURLString(env.BROWSER) },
           llmClient: new WorkersAIClient(env.AI),
           verbose: 1,
       });
       await stagehand.init();
       
       const agent = stagehand.agent();
       const result = await agent.execute(`I'd like to order a pepperoni pizza with extra cheese.
                                           Please deliver it to Cloudflare Austin office.
                                           Price should not be more than $20.`);


       return new Response(result.message);
   },
} satisfies ExportedHandler&lt;Env&gt;;</code></pre>
            <p>We can see that instead of adding step-by-step instructions, the agent is provided control. To actually pay, it would need access to a payment method such as a <a href="https://en.wikipedia.org/wiki/Controlled_payment_number"><u>virtual credit card</u></a>.</p><p>The prompt had some subtlety in that we’ve scoped the location to Cloudflare’s Austin office. This is because while the agent responds to us, it needs to understand our context. In this case, the agent operates out of Cloudflare edge, a location remote to us. This implies we are unlikely to pick up a pizza from this <a href="https://www.cloudflare.com/learning/cdn/glossary/data-center/"><u>data center</u></a> if it was ever delivered.</p><p>The more capabilities we provide to the agent, the more it has the ability to create some disruption. Instead of someone having to make 5 clicks at a slow rate of 1 request per 10 seconds, they’d have a program running in a data center possibly making all 5 requests in a second.</p><p>This agent is simple, but now imagine many thousands of these — some benign, some not — running at datacenter speeds. This is the challenge origins will face.</p>
    <div>
      <h2>Protecting origins</h2>
      <a href="#protecting-origins">
        
      </a>
    </div>
    <p>For humans to interact with the online world, they need a web browser and some peripherals with which to direct the behavior of that browser. Agents are another way of directing a browser, so it may be tempting to think that not much is actually changing from the origin's point of view. Indeed, the most obvious change from the origin's point of view is merely where traffic comes from:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/304j2MNDUNwAaipqmH2Jbt/35beb792bda327a6cf0db3b642bbc4d6/unnamed-1.png" />
          </figure><p>The reason this change is significant has to do with the tools the server has to manage traffic. Websites generally try to be as permissive as possible, but they also need to manage finite resources (bandwidth, CPU, memory, storage, and so on). There are a few basic ways to do this:</p><ol><li><p><b>Global security policy</b>: A server may opt to slow down, CAPTCHA, or even temporarily block requests from all users. This policy may be applied to an entire site, a specific resource, or to requests classified as being part of a known or likely attack pattern. Such mechanisms may be deployed in reaction to an observed spike in traffic, as in a DDoS attack, or in anticipation of a spike in legitimate traffic, as in <a href="https://developers.cloudflare.com/waiting-room/"><u>Waiting Room</u></a>.</p></li><li><p><b>Incentives</b>: Servers sometimes try to incentivize users to use the site when more resources are available. For instance, a server price may be lower depending on the location or request time. This could be implemented with a <a href="https://developers.cloudflare.com/rules/snippets/when-to-use/"><u>Cloudflare Snippet</u></a>.</p></li></ol><p>While both tools can be effective, they also sometimes cause significant collateral damage. For example, while rate limiting a website's login endpoint <a href="https://developers.cloudflare.com/waf/rate-limiting-rules/best-practices/#protecting-against-credential-stuffing"><u>can help prevent credential stuffing attacks</u></a>, it also degrades the user experience for non-attackers. Before resorting to such measures, servers will first try to apply the security policy (whether a rate limit, a CAPTCHA, or an outright block) to individual users or groups of users.</p><p>However, in order to apply a security policy to individuals, the server needs some way of identifying them. Historically, this has been done via some combination of IP addresses, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent"><u>User-Agent</u></a>, an account tied to the user identity (if available), and other fingerprints. Like most cloud service providers, Cloudflare has a <a href="https://developers.cloudflare.com/waf/rate-limiting-rules/best-practices/"><u>dedicated offering</u></a> for per-user rate limits based on such heuristics.</p><p>Fingerprinting works for the most part. However, it's unequitably distributed. On mobile, users <a href="https://blog.cloudflare.com/eliminating-captchas-on-iphones-and-macs-using-new-standard/#captchas-dont-work-in-mobile-environments-pats-remove-the-need-for-them"><u>have an especially difficult time solving CAPTCHA</u></a>s, when using a VPN they’re <a href="https://arstechnica.com/tech-policy/2023/07/meta-blocking-vpn-access-to-threads-in-eu/"><u>more</u></a> <a href="https://help.netflix.com/en/node/277"><u>likely</u></a> <a href="https://www.theregister.com/2015/10/19/bbc_cuts_off_vpn_to_iplayer/"><u>to</u></a> <a href="https://torrentfreak.com/hulu-blocks-vpn-users-over-piracy-concerns-140425/"><u>be</u></a> <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/troubleshooting/common-issues/"><u>blocked</u></a>, and when using <a href="https://www.peteresnyder.com/static/papers/speedreader-www2019.pdf"><u>reading mode</u></a> they can mess up their fingerprint, preventing rendering of the page.</p><p>Likewise, agentic AI only exacerbates the limitations of fingerprinting. Not only will more traffic be concentrated on a smaller source IP range, the agents themselves will run the same software and hardware platform, making it harder to distinguish honest from malicious users.</p><p>Something that could help is <a href="https://blog.cloudflare.com/web-bot-auth/"><u>Web Bot Auth</u></a>, which would allow agents to identify to the origin which platform they're operated by. However, we wouldn't want to extend this mechanism — intended for identifying the platform itself — to identifying individual users of the platforms, as this would create an unacceptable privacy risk for these users.</p><p>We need some way of implementing security controls for individual users without identifying them. But how? The Privacy Pass protocol provides <a href="https://blog.cloudflare.com/eliminating-captchas-on-iphones-and-macs-using-new-standard/#captchas-dont-work-in-mobile-environments-pats-remove-the-need-for-them"><u>a partial solution</u></a>.</p>
    <div>
      <h2>Privacy Pass and its limitations</h2>
      <a href="#privacy-pass-and-its-limitations">
        
      </a>
    </div>
    <p>Today, one of the most prominent use cases for Privacy Pass is to <a href="https://www.cloudflare.com/learning/bots/what-is-rate-limiting/"><u>rate limit</u></a> requests from a user to an origin, as we have <a href="https://blog.cloudflare.com/privacy-pass-standard/#privacy-pass-protocol"><u>discussed before</u></a>. The protocol works roughly as follows. The client is <b>issued</b> a number of <b>tokens</b>. Each time it wants to make a request, it <b>redeems</b> one of its tokens to the origin; the origin allows the request through only if the token is <b>fresh</b>, i.e., has never been observed before by the origin.</p><p>In order to use Privacy Pass for per-user rate-limiting, it's necessary to limit the number of tokens issued to each user (e.g., 100 tokens per user per hour). To rate limit an AI agent, this role would be fulfilled by the AI platform. To obtain tokens, the user would log in with the platform, and said platform would allow the user to get tokens from the issuer. The AI platform fulfills the <b>attester</b> role in Privacy Pass <a href="https://datatracker.ietf.org/doc/html/rfc9576"><u>parlance</u></a>. The attester is the party guaranteeing the per-user property of the rate limit. The AI platform, as an attester, is incentivized to enforce this token distribution as it stakes its reputation: Should it allow for too many tokens to be issued, the issuer could distrust them.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/62Rz5eS1UMm2pKorpowEGg/4949220bdf2fa3c39ccfa17d4df70fff/token__1_.png" />
          </figure><p>The issuance and redemption protocols are designed to have two properties:</p><ul><li><p>Tokens are <b>unforgeable</b>: only the issuer can issue valid tokens.</p></li><li><p>Tokens are <b>unlinkable: </b>no party, including the issuer, attester, or origin, can tell which user a token was issued to. </p></li></ul><p>These properties can be achieved using a <a href="https://csrc.nist.gov/glossary/term/cryptographic_primitive"><u>cryptographic primitive</u></a> called a <a href="https://blog.cloudflare.com/privacy-pass-the-math/"><u>blind signature</u></a><b> </b>scheme. In a conventional signature scheme, the signer uses its <b>private key</b> to produce a signature for a message. Later on, a verifier can use the signer’s <b>public key</b> to verify the signature. Blind signature schemes work in the same way, except that the message to be signed is blinded such that the signer doesn't know the message it's signing. The client “blinds” the message to be signed and sends it to the server, which then computes a blinded signature over the blinded message. The client obtains the final signature by unblinding the signature.  </p><p>This is exactly how the standardised Privacy Pass issuance protocols are defined by <a href="https://www.rfc-editor.org/rfc/rfc9578"><u>RFC 9578</u></a>:</p><ul>
  <li>
    <strong>Issuance:</strong> The user generates a random message 
    <strong>$k$</strong> 
    which we call the 
    <strong>nullifier</strong>. Concretely, this is just a random, 32-byte string. It then blinds the nullifier and sends it to the issuer. The issuer replies with a blind signature. Finally, the user unblinds the signature to get 
    <strong>$\sigma$</strong>, 
    a signature for the nullifier 
    <strong>$k$</strong>. The token is the pair 
    <strong>$(k, \sigma)$</strong>.
  </li>
  <li>
    <strong>Redemption:</strong> When the user presents 
    <strong>$(k, \sigma)$</strong>, 
    the origin checks that 
    <strong>$\sigma$</strong> 
    is a valid signature for the nullifier 
    <strong>$k$</strong> 
    and that 
    <strong>$k$</strong> 
    is fresh. If both conditions hold, then it accepts and lets the request through.
  </li>
</ul><p>Blind signatures are simple, cheap, and perfectly suited for many applications. However, they have some limitations that make them unsuitable for our use case.</p><p>First, the communication cost of the issuance protocol is too high. For each token issued, the user sends a 256-byte, blinded nullifier and the issuer replies with a 256-byte blind signature (assuming RSA-2048 is used). That's 0.5KB of additional communication per request, or 500KB for every 1,000 requests. This is manageable as we’ve seen in a <a href="https://eprint.iacr.org/2023/414.pdf"><u>previous experiment</u></a> for Privacy Pass, but not ideal. Ideally, the bandwidth would be sublinear in the rate limit we want to enforce. An alternative to blind signatures with lower compute time are Oblivious Pseudorandom Functions (<a href="https://datatracker.ietf.org/doc/rfc9497/"><u>VOPRF</u></a>), but the bandwidth is still asymptotically linear. We’ve <a href="https://blog.cloudflare.com/privacy-pass-the-math/"><u>discussed them in the past</u></a>, as they served as the basis for early deployments of Privacy Pass.</p><p>Second, blind signatures can't be used to rate-limit on a per-origin basis. Ideally, when issuing $N$ tokens to the client, the client would be able to redeem at most $N$ tokens at any origin server that can verify the token's validity. However, the client can't safely redeem the same token at more than one server because it would be possible for the servers to link those redemptions to the same client. What's needed is some mechanism for what we'll call <b>late origin-binding</b>: transforming a token for redemption at a particular origin in a way that's unlinkable to other redemptions of the same token.</p><p>Third, once a token is issued, it can't be revoked: it remains valid as long as the issuer's public key is valid. This makes it impossible for an origin to block a specific user if it detects an attack, or if its tokens are compromised. The origin can block the offending request, but the user can continue to make requests using its remaining token budget.</p>
    <div>
      <h2>Anonymous credentials and the future of Privacy Pass</h2>
      <a href="#anonymous-credentials-and-the-future-of-privacy-pass">
        
      </a>
    </div>
    <p>As noted by <a href="https://dl.acm.org/doi/pdf/10.1145/4372.4373"><u>Chaum</u></a> in 1985, an <b>anonymous credential</b> system allows users to obtain a credential from an issuer, and later prove possession of this credential, in an unlinkable way, without revealing any additional information. Also, it is possible to demonstrate that some attributes are attached to the credential.</p><p>One way to think of an anonymous credential is as a kind of blind signature with some additional capabilities: late-binding (link a token to an origin after issuance), multi-show (generate multiple tokens from a single issuer response), and expiration distinct from key rotation (token validity decoupled of the issuer cryptographic key validity). In the redemption flow for Privacy Pass, the client presents the unblinded message and signature to the server. To accept the redemption, the server needs to verify the signature. In an AC system, the client only presents a <b>part of the message</b>. In order for the server to accept the request, the client needs to prove to the server that it knows a valid signature for the entire message without revealing the whole thing.</p><p>The flow we described above would therefore include this additional <b>presentation</b> step. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7pb3ZDoAHbDLEt0mxtf67T/b6be11710a7df7a4df7d1c89788285a7/credentials__2_.png" />
          </figure><p>Note that the tokens generated through blind signatures or VOPRFs can only be used once, so they can be regarded as <i>single-use tokens</i>. However, there exists a type of anonymous credentials that allows tokens to be used multiple times. For this to work, the issuer grants a <i>credential</i> to the user, who can later derive at most <i>N</i> many single-use tokens for redemption. Therefore, the user can send multiple requests, at the expense of a single issuance session.  </p><p>The table below describes how blind signatures and anonymous credentials provide features of interest to rate limiting.</p><table><tr><td><p><b>Feature</b></p></td><td><p><b>Blind Signature</b></p></td><td><p><b>Anonymous Credential</b></p></td></tr><tr><td><p><b>Issuing Cost</b></p></td><td><p>Linear complexity: issuing 10 signatures is 10x as expensive as issuing one signature</p></td><td><p>Sublinear complexity: signing 10 attributes is cheaper than 10 individual signatures</p></td></tr><tr><td><p><b>Proof Capability</b></p></td><td><p>Only prove that a message has been signed</p></td><td><p>Allow efficient proving of partial statements (i.e., attributes)</p></td></tr><tr><td><p><b>State Management</b></p></td><td><p>Stateless</p></td><td><p>Stateful</p></td></tr><tr><td><p><b>Attributes</b></p></td><td><p>No attributes</p></td><td><p>Public (e.g. expiry time) and private state</p></td></tr></table><p>
  Let's see how a simple anonymous credential scheme works. The client's message consists of the pair 
  <strong>$(k, C)$</strong>, 
  where 
  <strong>$k$</strong> 
  is a 
  <strong>nullifier</strong> and 
  <strong>$C$</strong> 
  is a 
  <strong>counter</strong> representing the remaining number of times the client can access a resource. The value of the counter is controlled by the server: when the client redeems its credential, it presents both the nullifier and the counter. In response, the server checks that signature of the message is valid and that the nullifier is fresh, as before. Additionally, the server also
</p><ol><li><p>checks that the counter is greater than zero; and</p></li><li><p>decrements the counter issuing a new credential for the updated counter and a fresh nullifier.</p></li></ol><p>A blind signature could be used to meet this functionality. However, whereas the nullifier can be blinded as before, it would be necessary to handle the counter in plaintext so that the server can check that the counter is valid (Step 1) and update it (Step 2). This creates an obvious privacy risk since the server, which is in control of the counter, can use it to link multiple presentations by the same client. For example, when you reach out to buy a pepperoni pizza, the origin could assign you a special counter value, which eases fingerprinting when you present it a second time. Fortunately, there exist anonymous credentials designed to close this kind of privacy gap.</p><p>The scheme above is a simplified version of Anonymous Credit Tokens (<a href="https://datatracker.ietf.org/doc/draft-schlesinger-cfrg-act/"><u>ACT</u></a>), one of the anonymous credential schemes being considered for adoption by the <a href="https://datatracker.ietf.org/wg/privacypass/about/"><u>Privacy Pass working group</u></a> at IETF. The key feature of ACT is its <b>statefulness</b>: upon successful redemption, the server re-issues a new credential with updated nullifier and counter values. This creates a feedback loop between the client and server that can be used to express a variety of security policies.</p><p>By design, it's not possible to present ACT credentials multiple times simultaneously: the first presentation must be completed so that the re-issued credential can be presented in the next request. <b>Parallelism </b>is the key feature of Anonymous Rate-limited Credential (<a href="https://datatracker.ietf.org/doc/html/draft-yun-cfrg-arc-00"><u>ARC</u></a>), another scheme under discussion at the Privacy Pass working group. ARCs can be presented across multiple requests in parallel up to the presentation limit determined during issuance.</p><p>Another important feature of ARC is its support for late origin-binding: when a client is issued an ARC with presentation limit $N$, it can safely use its credential to present up to $N$ times to any origin that can verify the credential.</p><p>These are just examples of relevant features of some anonymous credentials. Some applications may benefit from a subset of them; others may need additional features. Fortunately, both ACT and ARC can be constructed from a small set of cryptographic primitives that can be easily adapted for other purposes.</p>
    <div>
      <h2>Building blocks for anonymous credentials</h2>
      <a href="#building-blocks-for-anonymous-credentials">
        
      </a>
    </div>
    <p>ARC and ACT share two primitives in common: <a href="https://eprint.iacr.org/2013/516.pdf"><b><u>algebraic MACs</u></b></a>, which provide for limited computations on the blinded message; and <a href="https://en.wikipedia.org/wiki/Zero-knowledge_proof"><b><u>zero-knowledge proofs (ZKP)</u></b></a> for proving validity of the part of the message not revealed to the server. Let's take a closer look at each.</p>
    <div>
      <h3>Algebraic MACs</h3>
      <a href="#algebraic-macs">
        
      </a>
    </div>
    <p>A Message Authenticated Code (MAC) is a cryptographic tag used to verify a message's authenticity (that it comes from the claimed sender) and integrity (that it has not been altered). Algebraic MACs are built from mathematical structures like <a href="https://en.wikipedia.org/wiki/Group_action"><u>group actions</u></a>. The algebraic structure gives them some additional functionality, one of them being a <i>homomorphism</i> that we can blind easily to conceal the actual value of the MAC. Adding a random value on an algebraic MAC blinds the value.</p><p>Unlike blind signatures, both ACT and ARC are only <i>privately</i> verifiable, meaning the issuer and the origin must both have the issuer's private key. Taking Cloudflare as an example, this means that a credential issued by Cloudflare can only be redeemed by an origin behind Cloudflare. Publicly verifiable variants of both are possible, but at an additional cost.</p>
    <div>
      <h3>Zero-Knowledge Proofs for linear relations</h3>
      <a href="#zero-knowledge-proofs-for-linear-relations">
        
      </a>
    </div>
    <p>Zero knowledge proofs (ZKP) allow us to prove a statement is true without revealing the exact value that makes the statement true. The ZKP is constructed by a prover in such a way that it can only be generated by someone who actually possesses the secret. The verifier can then run a quick mathematical check on this proof. If the check passes, the verifier is convinced that the prover's initial statement is valid. The crucial property is that the proof itself is just data that confirms the statement; it contains no other information that could be used to reconstruct the original secret.</p><p>For ARC and ACT, we want to prove <i>linear relations</i> of secrets. In ARC, a user needs to prove that different tokens are linked to the same original secret credential. For example, a user can generate a proof showing that a <i>request token</i> was derived from a valid <i>issued credential</i>. The system can verify this proof to confirm the tokens are legitimately connected, all without ever learning the underlying secret credential that ties them together. This allows the system to validate user actions while guaranteeing their privacy.</p><p>Proving simple linear relations can be extended to prove a number of powerful statements, for example that a number is in range. For example, this is useful to prove that you have a positive balance on your account. To prove your balance is positive, you prove that you can encode your balance in binary. Let’s say you can at most have 1024 credits in your account. To prove your balance is non-zero when it is, for example, 12, you prove two things simultaneously: first, that you have a set of binary bits, in this case 12=(1100)<sub>2</sub>, and second, that a linear equation using these bits (8*1 + 4*1 + 2*0 + 1*0) correctly adds up to your total committed balance. This convinces the verifier that the number is validly constructed without them learning the exact value. This is how it works for powers of two, but it can <a href="https://github.com/chris-wood/draft-arc/pull/38"><u>easily be extended to arbitrary ranges</u></a>.</p><p>The mathematical structure of algebraic MACs allows easy blinding and evaluation. The structure also allows for an easy proof that a MAC has been evaluated with the private key without revealing the MAC. In addition, ARC could use ZKPs to prove that a nonce has not been spent before. In contrast, ACT uses ZKPs to prove we have enough of a balance left on our token. The balance is subtracted homomorphically using more group structure.</p>
    <div>
      <h2>How much does this all cost?</h2>
      <a href="#how-much-does-this-all-cost">
        
      </a>
    </div>
    <p>Anonymous credentials allow for more flexibility, and have the potential to reduce the communication cost, compared to blind signatures in certain applications. To identify such applications, we need to measure the concrete communication cost of these new protocols. In addition, we need to understand how their CPU usage compares to blind signatures and oblivious pseudorandom functions.</p><p>We measure the time that each participant spends at each stage of some AC schemes. We also report the size of messages transmitted across the network. For ARC, ACT, and VOPRF, we'll use <a href="https://doi.org/10.17487/RFC9496"><u>ristretto255</u></a> as the prime group and SHAKE128 for hashing. For Blind RSA, we'll use a 2048-bit modulus and SHA-384 for hashing.</p><p>Each algorithm was implemented in Go, on top of the <a href="https://github.com/cloudflare/circl"><u>CIRCL</u></a> library. We plan to open source the code once the specifications of ARC and ACT begin to stabilize.</p><p>Let’s take a look at the most widely used deployment in Privacy Pass: Blind RSA. Redemption time is low, and most of the cost lies with the server at issuance time. Communication cost is mostly constant and in the order of 256 bytes.</p>
<div><table><thead>
  <tr>
    <th><span>Blind RSA</span><br /><a href="https://doi.org/10.17487/RFC9474"><span>RFC9474</span></a><span>(RSA-2048+SHA384)</span></th>
    <th><span>1 Token</span></th>
  </tr>
  <tr>
    <th><span>Time</span></th>
    <th><span>Message Size</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Issuance</span></td>
    <td><span>Client (Blind)</span></td>
    <td><span>63 µs</span></td>
    <td><span>256 B</span></td>
  </tr>
  <tr>
    <td><span>Server (Evaluate)</span></td>
    <td><span>2.69 ms</span></td>
    <td><span>256 B</span></td>
  </tr>
  <tr>
    <td><span>Client (Finalize)</span></td>
    <td><span>37 µs</span></td>
    <td><span>256 B</span></td>
  </tr>
  <tr>
    <td><span>Redemption</span></td>
    <td><span>Client</span></td>
    <td><span> –</span></td>
    <td><span>300 B</span></td>
  </tr>
  <tr>
    <td><span>Server</span></td>
    <td><span>37 µs</span></td>
    <td><span>–</span></td>
  </tr>
</tbody></table></div><p>When looking at VOPRF, verification time on the server is slightly higher than for Blind RSA, but communication cost and issuance are much faster. Evaluation time on the server is 10x faster for 1 token, and more than 25x faster when using <a href="https://datatracker.ietf.org/doc/draft-ietf-privacypass-batched-tokens/"><u>amortized token issuance</u></a>. Communication cost per token is also more appealing, with a message size at least 3x lower.</p>
<div><table><thead>
  <tr>
    <th><span>VOPRF</span><br /><a href="https://doi.org/10.17487/RFC9497"><span>RFC9497</span></a><span>(Ristretto255+SHA512)</span></th>
    <th><span>1 Token</span></th>
    <th><span>1000 Amortized issuances</span></th>
  </tr>
  <tr>
    <th><span>Time</span></th>
    <th><span>Message Size</span></th>
    <th><span>Time </span><br /><span>(per token)</span></th>
    <th><span>Message Size </span><br /><span>(per token)</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Issuance</span></td>
    <td><span>Client (Blind)</span></td>
    <td><span>54 µs</span></td>
    <td><span>32 B</span></td>
    <td><span>54 µs</span></td>
    <td><span>32 B</span></td>
  </tr>
  <tr>
    <td><span>Server (Evaluate)</span></td>
    <td><span>260 µs</span></td>
    <td><span>96 B</span></td>
    <td><span>99 µs</span></td>
    <td><span>32.064 B</span></td>
  </tr>
  <tr>
    <td><span>Client (Finalize)</span></td>
    <td><span>376 µs</span></td>
    <td><span>64 B</span></td>
    <td><span>173 µs</span></td>
    <td><span>64 B</span></td>
  </tr>
  <tr>
    <td><span>Redemption</span></td>
    <td><span>Client</span></td>
    <td><span> –</span></td>
    <td><span>96 B</span></td>
    <td><span>–</span></td>
  </tr>
  <tr>
    <td><span>Server</span></td>
    <td><span>57 µs</span></td>
    <td><span>–</span></td>
  </tr>
</tbody></table></div><p>This makes VOPRF tokens appealing for applications requiring a lot of tokens that can accept a slightly higher redemption cost, and that don’t need public verifiability.</p><p>Now, let’s take a look at the figures for ARC and ACT anonymous credential schemes. For both schemes we measure the time to issue a credential that can be presented at most $N=1000$ times.</p>
<div><table><thead>
  <tr>
    <th><span>Issuance</span><br /><span>Credential Generation</span></th>
    <th><span>ARC</span></th>
    <th><span>ACT</span></th>
  </tr>
  <tr>
    <th><span>Time</span></th>
    <th><span>Message Size</span></th>
    <th><span>Time</span></th>
    <th><span>Message Size</span></th>
  </tr></thead>
<tbody>
  <tr>
    <td><span>Client (Request)</span></td>
    <td><span>323 µs</span></td>
    <td><span>224 B</span></td>
    <td><span>64 µs</span></td>
    <td><span>141 B</span></td>
  </tr>
  <tr>
    <td><span>Server (Response)</span></td>
    <td><span>1349 µs</span></td>
    <td><span>448 B</span></td>
    <td><span>251 µs</span></td>
    <td><span>176 B</span></td>
  </tr>
  <tr>
    <td><span>Client (Finalize)</span></td>
    <td><span>1293 µs</span></td>
    <td><span>128 B</span></td>
    <td><span>204 µs</span></td>
    <td><span>176 B</span></td>
  </tr>
  <tr>
    <td></td>
  </tr>
  <tr>
    <td><span>Redemption</span><br /><span>Credential Presentation</span></td>
    <td><span>ARC</span></td>
    <td><span>ACT</span></td>
  </tr>
  <tr>
    <td><span>Time</span></td>
    <td><span>Message Size</span></td>
    <td><span>Time</span></td>
    <td><span>Message Size</span></td>
  </tr>
  <tr>
    <td><span>Client (Present)</span></td>
    <td><span>735 µs</span></td>
    <td><span>288 B</span></td>
    <td><span> 1740 µs</span></td>
    <td><span>1867 B</span></td>
  </tr>
  <tr>
    <td><span>Server (Verify/Refund)</span></td>
    <td><span>740 µs</span></td>
    <td><span>–</span></td>
    <td><span>1785 µs</span></td>
    <td><span>141 B</span></td>
  </tr>
  <tr>
    <td><span>Client (Update)</span></td>
    <td><span>–</span></td>
    <td><span>–</span></td>
    <td><span>508 µs</span></td>
    <td><span>176 B</span></td>
  </tr>
</tbody></table></div><p>As we would hope, the communication cost and the server’s runtime is much lower than a batched issuance with either Blind RSA or VOPRF. For example, a VOPRF issuance of 1000 tokens takes 99 ms (99 µs per token) <i>vs</i> 1.35 ms for issuing one ARC credential that allows for 1000 presentations. This is about 70x faster. The trade-off is that presentation is more expensive, both for the client and server.</p><p>How about ACT? Like ARC, we would expect the communication cost of issuance grows much slower with respect to the credits issued. Our implementation bears this out. However, there are some interesting performance differences between ARC and ACT: issuance is much cheaper for ACT than it is for ARC, but redemption is the opposite.</p><p>What's going on? The answer has largely to do with what each party needs to prove with ZKPs at each step. For example, during ACT redemption, the client proves to the server (in zero-knowledge) that its counter $C$ is in the desired range, i.e., $0 \leq C \leq N$. The proof size is on the order of $\log_{2} N$, which accounts for the larger message size. In the current version, ARC redemption does not involve range proofs, but a range proof may be added in a <a href="http://mailarchive.ietf.org/arch/msg/privacy-pass/A3VHUdHqhslwBzYEQjcaXzYQAxQ/"><u>future version</u></a>. Meanwhile, the statements the client and server need to prove during ARC issuance are a bit more complicated than for ARC presentation, which accounts for the difference in runtime there.</p><p>The advantage of anonymous credentials, as discussed in the previous sections, is that issuance only has to be performed once. When a server evaluates its cost, it takes into account the cost of all issuances and the cost of all verifications. At present, only accounting for credentials costs, it’s cheaper for a server to issue and verify tokens than verify an anonymous credential presentation.</p><p>The advantage of multiple-use anonymous credentials is that instead of the issuer generating $N$ tokens, the bulk of computation is offloaded to the clients. This is more scoped. Late origin binding allows them to work for multiple origins/namespace, range proof to decorrelate expiration from key rotation, and refund to provide a dynamic rate limit. Their current applications are dictated by the limitation of single-use token based schemes, more than by the added efficiency they provide. This seems to be an exciting area to explore, and see if closing the gap is possible.</p>
    <div>
      <h2>Managing agents with anonymous credentials</h2>
      <a href="#managing-agents-with-anonymous-credentials">
        
      </a>
    </div>
    <p>Managing agents will likely require features from both ARC and ACT.</p><p>ARC already has much of the functionality we need: it supports rate limiting, is communication-efficient, and it supports late origin-binding. Its main downside is that, once an ARC credential is issued, it can't be revoked. A malicious user can always make up to <i>N</i> requests to any origin it wants.</p><p>We can allow for a limited form of revocation by pairing ARC with blind signatures (or VOPRF). Each presentation of the ARC credential is accompanied by a Privacy Pass token: upon successful presentation, the client is issued another Privacy Pass token it can use during the next presentation. To revoke a credential, the server would simply not re-issue the token:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6EiHmkbLef6kXsQU473fcX/d1d4018eaf2abd42b9690ae5d01494dc/image1.png" />
          </figure><p>This scheme is already quite useful. However, it has some important limitations:</p><ul><li><p>Parallel presentation across origins is not possible: the client must wait for the request to one origin to succeed before it can initiate a request to a second origin.</p></li><li><p>Revocation is <i>global</i> rather than per-origin, meaning the credential is not only revoked for the origin to whom it was presented, but for every origin it can be presented to. We suspect this will be undesirable in some cases. For example, an origin may want to revoke if a request violates its <code>robots.txt</code> policy; but the same request may have been accepted by other origins.  </p></li></ul><p>A more fundamental limitation of this design is that the decision to revoke can only be made on the basis of a single request — the one in which the credential was presented. It may be risky to decide to block a user on the basis of a single request; in practice, attack patterns may only emerge across many requests. ACT's statefulness enables at least a rudimentary form of this kind of defense. Consider the following scheme:</p><ul><li><p><b>Issuance: </b>The client is issued an ARC with presentation limit $N=1$.</p></li><li><p><b>Presentation:</b></p><ul><li><p>When the client presents its ARC credential to an origin for the first time, the server issues an ACT credential with a valid initial state.</p></li><li><p>When the client presents an ACT with valid state (e.g., credit counter greater than 0), the origin either:</p><ul><li><p>refuses to issue a new ACT, thereby revoking the credential. It would only do so if it had high confidence that the request was part of an attack; or</p></li><li><p>issues a new ACT with state updated to reduce the ACT credit by the amount of resources consumed while processing the request.</p></li></ul></li></ul></li></ul><p>Benign requests wouldn't change the state by much (if at all), but suspicious requests might impact the state in a way that gets the user closer to their rate limit much faster.</p>
    <div>
      <h2>Demo</h2>
      <a href="#demo">
        
      </a>
    </div>
    <p>To see how this idea works in practice, let's look at a working example that uses the <a href="https://developers.cloudflare.com/agents/model-context-protocol/"><u>Model Context Protocol</u></a>. The demo below is built using<a href="https://developers.cloudflare.com/agents/model-context-protocol/tools/"> <u>MCP Tools</u></a>. <a href="https://modelcontextprotocol.info/tools/"><u>Tools</u></a> are extensions the AI agent can call to extend its capabilities. They don't need to be integrated at release time within the MCP client. This provides a nice and easy prototyping avenue for anonymous credentials.</p><p>Tools are offered by the server via an MCP compatible interface. You can see details on how to build such MCP servers in a <a href="https://blog.cloudflare.com/remote-model-context-protocol-servers-mcp/"><u>previous blog</u></a>.</p><p>In our pizza context, this could look like a pizzeria that offers you a voucher. Each voucher gets you 3 pizza slices. Mocking a design, an integration within a chat application could look as follows:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5WD5MYoSMYGyRW2biwe6j4/bde101967276a72d48d9e494a23db5fa/image5.png" />
          </figure>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5SEqaVpwFxS1D21oyjjbN8/80dde2484f43c15e206ecfda991c286a/image9.png" />
          </figure><p>The first panel presents all tools exposed by the MCP server. The second one showcases an interaction performed by the agent calling these tools.</p><p>To look into how such a flow would be implemented, let’s write the MCP tools, offer them in an MCP server, and manually orchestrate the calls with the <a href="https://modelcontextprotocol.io/docs/tools/inspector"><u>MCP Inspector</u></a>.</p><p>The MCP server should provide two tools:</p><ul><li><p><code>act-issue </code>which issues an ACT credential valid for 3 requests. The code used here is an earlier version of the IETF draft which has some limitations.</p></li><li><p><code>act-redeem</code> makes a presentation of the local credential, and fetches our pizza menu.</p></li></ul><p>First, we run <code>act-issue</code>. At this stage, we could ask the agent to run an<a href="https://modelcontextprotocol.info/specification/draft/basic/authorization/"> <u>OAuth flow</u></a>, fetch an internal authentication endpoint, or to compute a proof of work.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6sLS7jMfTHPjVW5vMvsTWX/2d2b10fdb12c64f0e33fee89e09eab85/image10.png" />
          </figure><p>This gives us 3 credits to spend against an origin. Then, we run <code>act-redeem</code></p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1YTc0Wohrsqw3hizAOmJjU/4534cccbc490ad0aa09522a3875693af/image8.png" />
          </figure><p>Et voilà. If we run <code>act-redeem</code> once more, we see we have one fewer credit.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/a0zmBfl46hX33hWoXyGyX/86649d9f435562c95a85ec72fbf33022/image3.png" />
          </figure><p>You can test it yourself, here are the <a href="https://github.com/cloudflareresearch/anonymous-credentials-agent-demo"><u>source codes</u></a> available. The MCP server is written in<a href="https://github.com/modelcontextprotocol/rust-sdk/"> <u>Rust</u></a> to integrate with the <a href="https://github.com/SamuelSchlesinger/anonymous-credit-tokens/stargazers"><u>ACT rust</u></a> library. The <a href="https://act-client-demo.cloudflareresearch.com/"><u>browser-based client</u></a> works similarly, check it out.</p>
    <div>
      <h2>Moving further</h2>
      <a href="#moving-further">
        
      </a>
    </div>
    <p>In this post, we’ve presented a concrete approach to rate limit agent traffic. It is in full control of the client, and is built to protect the user's privacy. It uses emerging standards for anonymous credentials, integrates with MCP, and can be readily deployed on Cloudflare Workers.</p><p>We're on the right track, but there are still questions that remain. As we touched on before, a notable limitation of both ARC and ACT is that they are only <i>privately verifiable</i>. This means that the issuer and origin need to share a private key, for issuing and verifying the credential respectively. There are likely to be deployment scenarios for which this isn't possible. Fortunately, there may be a path forward for these cases using<i> pairing-</i>based cryptography, as in the <a href="https://datatracker.ietf.org/doc/draft-irtf-cfrg-bbs-signatures/"><u>BBS signature specification</u></a> making its way through IETF. We’re also exploring post-quantum implications in a <a href="https://blog.cloudflare.com/pq-anonymous-credentials/"><u>concurrent post</u></a>.</p><p>If you are an agent platform, an agent developer, or a browser, all our code is available on <a href="https://github.com/cloudflareresearch/anonymous-credentials-agent-demo"><u>GitHub</u></a> for you to experiment. Cloudflare is actively working on vetting this approach for real-world use cases.</p><p>The specification and discussion are happening within the IETF and W3C. This ensures the protocols are built in the open, and receive participation from experts. Improvements are still to be made to clarify the right performance-to-privacy tradeoff, or even the story to deploy on the open web.</p><p>If you’d like to help us, <a href="https://blog.cloudflare.com/cloudflare-1111-intern-program/"><u>we’re hiring 1,111 interns</u></a> over the course of next year, and have <a href="https://www.cloudflare.com/careers/early-talent/"><u>open positions</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Research]]></category>
            <category><![CDATA[Rate Limiting]]></category>
            <guid isPermaLink="false">1znqOjDHsm8kxWujPMhsgA</guid>
            <dc:creator>Thibault Meunier</dc:creator>
            <dc:creator>Christopher Patton</dc:creator>
            <dc:creator>Lena Heimberger</dc:creator>
            <dc:creator>Armando Faz-Hernández</dc:creator>
        </item>
        <item>
            <title><![CDATA[Policy, privacy and post-quantum: anonymous credentials for everyone]]></title>
            <link>https://blog.cloudflare.com/pq-anonymous-credentials/</link>
            <pubDate>Thu, 30 Oct 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ The world is adopting anonymous credentials for digital privacy, but these systems are vulnerable to quantum computers. This post explores the cryptographic challenges and promising research paths toward building new, quantum-resistant credentials from the ground up. ]]></description>
            <content:encoded><![CDATA[ <p></p><p>The Internet is in the midst of one of the most complex transitions in its history: the migration to <a href="https://www.cloudflare.com/en-gb/pqc/"><u>post-quantum (PQ) cryptography.</u></a> Making a system safe against quantum attackers isn't just a matter of replacing elliptic curves and RSA with PQ alternatives, such as <a href="https://csrc.nist.gov/pubs/fips/203/final"><u>ML-KEM</u></a> and <a href="https://csrc.nist.gov/pubs/fips/204/final"><u>ML-DSA</u></a>. These algorithms have higher costs than their classical counterparts, making them unsuitable as drop-in replacements in many situations.</p><p>Nevertheless, we're <a href="https://blog.cloudflare.com/pq-2025/"><u>making steady progress</u></a> on the most important systems. As of this writing, <a href="https://radar.cloudflare.com/adoption-and-usage#post-quantum-encryption"><u>about 50%</u></a> of <a href="https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/"><u>TLS connections</u></a> to Cloudflare's edge are safe against <a href="https://en.wikipedia.org/wiki/Harvest_now,_decrypt_later"><u>store-now/harvest-later attacks</u></a>. Quantum safe authentication is further out, as it will require more significant changes to how certificates work. Nevertheless, this year we've <a href="https://blog.cloudflare.com/bootstrap-mtc/"><u>taken a major step</u></a> towards making TLS deployable at scale with PQ certificates.</p><p>That said, TLS is only the lowest hanging fruit. There are <a href="https://github.com/fancy-cryptography/fancy-cryptography"><u>many more ways</u></a> we have come to rely on cryptography than key exchange and authentication and which aren’t as easy to migrate. In this blog post, we'll take a look at <b>Anonymous Credentials (ACs)</b>.</p><p>ACs solve a common privacy dilemma: how to prove a specific fact (for example that one has had a valid driver’s license for more than three years) without over-sharing personal information (like the place of birth)? Such problems are fundamental to a number of use cases, and ACs may provide the foundation we need to make these applications as private as possible.</p><p>Just like for TLS, the central question for ACs is whether there are drop-in, PQ replacements for its classical primitives that will work at the scale required, or will it be necessary to re-engineer the application to mitigate the cost of PQ.</p><p>We'll take a stab at answering this question in this post. We'll focus primarily on an emerging use case for ACs described in a <a href="https://blog.cloudflare.com/private-rate-limiting/"><u>concurrent post</u></a>: rate-limiting requests from agentic AI platforms and users. This demanding, high-scale use case is the perfect lens through which to evaluate the practical readiness of today's post-quantum research. We'll use it as our guiding problem to measure each cryptographic approach.</p><p>We'll first explore the current landscape of classical AC adoption across the tech industry and the public sector. Then, we’ll discuss what cryptographic researchers are currently looking into on the post-quantum side. Finally, we’ll take a look at what it'll take to bridge the gap between theory and real-world applications.</p><p>While anonymous credentials are only seeing their first real-world deployments in recent years, it is critical to start thinking about the post-quantum challenge concurrently. This isn’t a theoretical, too-soon problem given the store-now decrypt-later threat. If we wait for mass adoption before solving post-quantum anonymous credentials, ACs risk being dead on arrival. Fortunately, our survey of the state of the art shows the field is close to a practical solution. Let’s start by reviewing real-world use-cases of ACs. </p>
    <div>
      <h2>Real world (classical) anonymous credentials</h2>
      <a href="#real-world-classical-anonymous-credentials">
        
      </a>
    </div>
    <p>In 2026, the European Union is <a href="https://eur-lex.europa.eu/eli/reg/2024/1183/oj"><u>set to launch its digital identity wallet</u></a>, a system that will allow EU citizens, residents and businesses to digitally attest to their personal attributes. This will enable them, for example, to display their driver’s license on their phone or <a href="https://educatedguesswork.org/posts/age-verification-id/"><u>perform age</u></a> <a href="https://soatok.blog/2025/07/31/age-verification-doesnt-need-to-be-a-privacy-footgun/"><u>verification</u></a>. Cloudflare's use cases for ACs are a bit different and revolve around keeping our customers secure by, for example, rate limiting bots and humans as we <a href="https://blog.cloudflare.com/privacy-pass-standard/"><u>currently do with Privacy Pass</u></a>. The EU wallet is a massive undertaking in identity provisioning, and our work operates at a massive scale of traffic processing. Both initiatives are working to solve a shared fundamental problem: allowing an entity to prove a specific attribute about themselves without compromising their privacy by revealing more than they have to.</p><p>The EU's goal is a fully mobile, secure, and user-friendly digital ID. The current technical plan is ambitious, as laid out in the <a href="https://ec.europa.eu/digital-building-blocks/sites/spaces/EUDIGITALIDENTITYWALLET/pages/900014854/Version+2.0+of+the+Architecture+and+Reference+Framework+now+available"><u>Architecture Reference Framework (ARF)</u></a>. It defines the key privacy goals of unlinkability to guarantee that if a user presents attributes multiple times, the recipients cannot link these separate presentations to conclude that they concern the same user. However, currently proposed solutions fail to achieve this. The framework correctly identifies the core problem: attestations contain <i>unique, fixed elements such as hash values, […], public keys, and signatures</i> that colluding entities could store and compare to track individuals.</p><p>In its present form, the ARF's recommendation to mitigate cross-session linkability is <i>limited-time attestations</i>. The framework acknowledges in the text that this would <i>only partially mitigate Relying Party linkability</i>. An alternative proposal that would mitigate linkability risks are single-use credentials. They are not considered at the moment due to <i>complexity and management overhead</i>. The framework therefore leans on <i>organisational and enforcement measure</i>s to deter collusion instead of providing a stronger guarantee backed by cryptography.</p><p>This reliance on trust assumptions could become problematic, especially in the sensitive context of digital identity. When asked for feedback, c<a href="https://github.com/eu-digital-identity-wallet/eudi-doc-architecture-and-reference-framework/issues/200"><u>ryptographic researchers agree</u></a> that the proper solution would be to adopt anonymous credentials. However, this solution presents a long-term challenge. Well-studied methods for anonymous credentials, such as those based on <a href="https://datatracker.ietf.org/doc/draft-irtf-cfrg-bbs-signatures/"><u>BBS signatures</u></a>, are vulnerable to quantum computers. While some <a href="https://datatracker.ietf.org/doc/rfc9474/"><u>anonymous</u></a> <a href="https://datatracker.ietf.org/doc/draft-schlesinger-cfrg-act/"><u>schemes</u></a> are PQ-unlinkable, meaning that user privacy is preserved even when cryptographically relevant quantum computers exist, new credentials could be forged. This may be an attractive target for, say, a nation state actor.</p><p>New cryptography also faces deployment challenges: in the EU, only approved cryptographic primitives, as listed in the <a href="https://www.sogis.eu/documents/cc/crypto/SOGIS-Agreed-Cryptographic-Mechanisms-1.3.pdf"><u>SOG-IS catalogue,</u></a> can be used. At the time of writing, this catalogue is limited to established algorithms such as RSA or ECDSA. But when it comes to post-quantum cryptography, SOG-IS is <a href="https://www.sogis.eu/documents/cc/crypto/SOGIS-Agreed-Cryptographic-Mechanisms-1.3.pdf"><u>leaving the problem wide open</u></a>.</p><p>The wallet's first deployment will not be quantum-secure. However, with the transition to post-quantum algorithms being ahead of us, as soon as 2030 for high-risk use cases per <a href="https://digital-strategy.ec.europa.eu/en/library/coordinated-implementation-roadmap-transition-post-quantum-cryptography"><u>the EU roadma</u></a>p, research in a post-quantum compatible alternative for anonymous credentials is critical. This will encompass<b> </b><i>standardizing more cryptography.</i></p><p>Regarding existing large scale deployments, the US has allowed digital ID on smartphones since 2024. They <a href="https://www.tsa.gov/digital-id/participating-states"><u>can be used at TSA checkpoints</u></a> for instance. The <a href="https://www.dhs.gov/science-and-technology/privacy-preserving-digital-credential-wallets-verifiers"><u>Department of Homeland Security lists funding for six privacy-preserving digital credential wallets and verifiers on their website.</u></a> This early exploration and engagement is a positive sign, and highlights the need to plan for privacy-preserving presentations. </p><p>Finally, ongoing efforts at the Internet Engineering Task Force (IETF)<b> </b>aim<b> </b>to build a more private Internet by standardizing advanced cryptographic techniques. Active individual drafts (i.e., not yet adopted by a working group), such as <a href="https://datatracker.ietf.org/doc/draft-google-cfrg-libzk/"><u>Longfellow</u></a> and Anonymous Credit Tokens (<a href="https://datatracker.ietf.org/doc/draft-schlesinger-cfrg-act/"><u>ACT</u></a>), and adopted drafts like Anonymous Rate-limited Credentials (<a href="https://datatracker.ietf.org/doc/draft-yun-privacypass-crypto-arc/"><u>ARC</u></a>), propose more flexible multi-show anonymous credentials that incorporate developments over the last several years. At IETF 117 in 2023, <a href="https://www.irtf.org/anrw/2023/slides-117-anrw-sessc-not-so-low-hanging-fruit-security-and-privacy-research-opportunities-for-ietf-protocols-00.pdf"><u>post-quantum anonymous credentials and deployable generic anonymous credentials were presented as a research opportunity</u></a>. Check out our <a href="https://blog.cloudflare.com/private-rate-limiting/"><u>post on rate limiting agents</u></a> for details.</p><p>Before we get into the state-of-the-art for PQ, allow us to try to crystalize a set of requirements for real world applications.</p>
    <div>
      <h3>Requirements</h3>
      <a href="#requirements">
        
      </a>
    </div>
    <p>Given the diversity of use cases, adoption of ACs will be made easier by the fact that they can be built from a handful of powerful primitives. (More on this in our <a href="https://blog.cloudflare.com/private-rate-limiting/"><u>concurrent post</u></a>.) As we'll see in the next section, we don't yet have drop-in, PQ alternatives for these kinds of primitives. The "building blocks" of PQ ACs are likely to look quite different, and we're going to know something about what we're building towards.</p><p>For our purposes, we can think of an anonymous credential as a kind of fancy <a href="https://en.wikipedia.org/wiki/Blind_signature"><b><u>blind signature</u></b></a>. What's that you ask? A blind signature scheme has two phases: <b>issuance</b>, in which the server signs a message chosen by the client; and <b>presentation</b>, in which the client reveals the message and the signature to the server. The scheme should be <b>unlinkable</b> in the sense that the server can't link any message and signature to the run of the issuance protocol in which it was produced. It should also be <b>unforgeable</b> in the sense that no client can produce a valid signature without interacting with the server.</p><p>The key difference between ACs and blind signatures is that, during presentation of an AC, the client only presents <i>part of the message</i> in plaintext; the rest of the message is kept secret. Typically, the message has three components:</p><ol><li><p>Private <b>state</b>, such as a counter that, for example, keeps track of the number of times the credential was presented. The client would prove to the server that the state is "valid", for example, a counter with value $0 \leq C \leq N$, without revealing $C$. In many situations, it's desirable to allow the server to update this state upon successful presentation, for example, by decrementing the counter. In the context of rate limiting, this is the number of how many requests are left for a credential.</p></li><li><p>A random value called the <b>nullifier</b> that is revealed to the server during presentation. In rate-limiting, the nullifier prevents a user from spending a credential with a given state more than once.</p></li><li><p>Public <b>attributes</b> known to both the client and server that bind the AC to some application context. For example, this might represent the window of time in which the credential is valid (without revealing the exact time it was issued).</p></li></ol><p>Such ACs are well-suited for rate limiting requests made by the client. Here the idea is to prevent the client from making more than some maximum number of requests during the credential's lifetime. For example, if the presentation limit is 1,000 and the validity window is one hour, then the clients can make up to 0.27 requests/second on average before it gets throttled.</p><p>It's usually desirable to enforce rate limits on a <b>per-origin</b> basis. This means that if the presentation limit is 1,000, then the client can make at most 1,000 requests to any website that can verify the credential. Moreover, it can do so safely, i.e., without breaking unlinkability across these sites.</p><p>The current generation of ACs being considered for standardization at IETF are only <b>privately verifiable,</b> meaning the server issuing the credential (the <b>issuer</b>) must share a private key with the server verifying the credential (the <b>origin</b>). This will be sufficient for some deployment scenarios, but many will require <b>public verifiability</b>, where the origin only needs the issuer's public key. This is possible with BBS-based credentials, for example.</p><p>Finally, let us say a few words about round complexity. An AC is <b>round optimal</b> if issuance and presentation both complete in a single HTTP request and response. In our survey of PQ ACs, we found a number of papers that discovered neat tricks that reduce bandwidth (the total number of bits transferred between the client and server) at the cost of additional rounds. However, for use cases like ours, <b>round optimality</b> is an absolute necessity, especially for presentation. Not only do multiple rounds have a high impact on latency, they also make the implementation far more complex.</p><p>Within these constraints, our goal is to develop PQ ACs that have as low communication cost (i.e., bandwidth consumption) and runtime as possible in the context of rate-limiting.</p>
    <div>
      <h2>"Ideal world" (PQ) anonymous credentials</h2>
      <a href="#ideal-world-pq-anonymous-credentials">
        
      </a>
    </div>
    <p>The academic community has produced a number of promising post-quantum ACs. In our survey of the state of the art, we evaluated several leading schemes, scoring them on their underlying primitives and performance to determine which are truly ready for the Internet. To understand the challenges, it is essential to first grasp the cryptographic building blocks used in ACs today. We’ll now discuss some of the core concepts that frequently appear in the field.</p>
    <div>
      <h3>Relevant cryptographic paradigms</h3>
      <a href="#relevant-cryptographic-paradigms">
        
      </a>
    </div>
    
    <div>
      <h4>Zero-knowledge proofs</h4>
      <a href="#zero-knowledge-proofs">
        
      </a>
    </div>
    <p>Zero-knowledge proofs (ZKPs) are a cryptographic protocol that allows a <i>prover</i> to convince a <i>verifier</i> that a statement is true without revealing the secret information, or <i>witness</i>. ZKPs play a central role in ACs: they allow proving statements of the secret part of the credential's state without revealing the state itself. This is achieved by transforming the statement into a mathematical representation, such as a set of polynomial equations over a finite field. The prover then generates a proof by performing complex operations on this representation, which can only be completed correctly if they possess the valid witness.</p><p>General-purpose ZKP systems, like <a href="https://eprint.iacr.org/2018/046"><u>Scalable Transparent Arguments of Knowledge (STARKs)</u></a>, can prove the integrity of <i>any</i> computation up to a certain size. In a STARK-based system, the computational trace is represented as a <i>set of polynomials</i>. The prover then constructs a proof by evaluating these polynomials and committing to them using cryptographic hash functions. The verifier can then perform a quick probabilistic check on this proof to confirm that the original computation was executed correctly. Since the proof itself is just a collection of hashes and sampled polynomial values, it is secure against quantum computers, providing a statistically sound guarantee that the claimed result is valid.</p>
    <div>
      <h4>Cut-and-Choose</h4>
      <a href="#cut-and-choose">
        
      </a>
    </div>
    <p>Cut-and-choose is a cryptographic technique designed to ensure a prover’s honest behaviour by having a verifier check a random subset of their work. The prover first commits to multiple instances of a computation, after which the verifier randomly chooses a portion to be <i>cut open</i> by revealing the underlying secrets for inspection. If this revealed subset is correct, the verifier gains high statistical confidence that the remaining, un-opened instances are also correct.</p><p>This technique is important because while it is a generic tool used to build protocols secure against malicious adversaries, it also serves as a crucial case study. Its security is not trivial; for example, practical attacks on cut-and-choose schemes built with (post-quantum) homomorphic encryption have succeeded by <a href="https://eprint.iacr.org/2025/1890.pdf"><u>attacking the algebraic structure of the encoding</u></a>, not the encryption itself. This highlights that even generic constructions must be carefully analyzed in their specific implementation to prevent subtle vulnerabilities and information leaks.</p>
    <div>
      <h4>Sigma Protocols</h4>
      <a href="#sigma-protocols">
        
      </a>
    </div>
    <p><a href="https://datatracker.ietf.org/doc/draft-irtf-cfrg-sigma-protocols/01/"><u>Sigma protocols</u></a> follow a more structured approach that does not require us to throw away any computations. The <a href="https://pages.cs.wisc.edu/~mkowalcz/628.pdf"><u>three-move protocol</u></a> starts with a <i>commitment</i> phase where the prover generates some randomness<i>,</i> which is added to the input to generate the commitment, and sends the commitment to the verifier. Then, the verifier <i>challenges </i>the prover with an unpredictable challenge. To finish the proof, the prover provides a <i>response</i> in which they combine the initial randomness with the verifier’s challenge in a way that is only possible if the secret value, such as the solution to a discrete logarithm problem, is known.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1ihEZ5KhWBQ0PZF5pTc0Bi/e35de03a89af0c2254bcc114041f6904/image4.png" />
          </figure><p><sup>Depiction of a Sigma protocol flow, where the prover commits to their witness $w$, the verifier challenges the prover to prove knowledge about $w$, and the prover responds with a mathematical statement that the verifier can either accept or reject.</sup></p><p>In practice, the prover and verifier don't run this interactive protocol. Instead, they make it non-interactive using a technique known as the <a href="https://link.springer.com/content/pdf/10.1007/3-540-47721-7_12.pdf"><u>Fiat-Shamir transformation</u></a>. The idea is that the prover generates the challenge <i>itself</i>, by deriving it from its own commitment. It may sound a bit odd, but it works quite well. In fact, it's the basis of signatures like ECDSA and even PQ signatures like ML-DSA.</p>
    <div>
      <h4>MPC in the head</h4>
      <a href="#mpc-in-the-head">
        
      </a>
    </div>
    <p>Multi-party computation (MPC) is a cryptographic tool that allows multiple parties to jointly compute a function over their inputs without revealing their individual inputs to the other parties. <a href="https://web.cs.ucla.edu/~rafail/PUBLIC/77.pdf"><u>MPC in the Head</u></a> (MPCitH) is a technique to generate zero-knowledge proofs by simulating a multi-party protocol <i>in the head</i> of the prover.</p><p>The prover simulates the state and communication for each virtual party, commits to these simulations, and shows the commitments to the verifier. The verifier then challenges the prover to open a subset of these virtual parties. Since MPC protocols are secure even if a minority of parties are dishonest, revealing this subset doesn't leak the secret, yet it convinces the verifier that the overall computation was correct. </p><p>This paradigm is particularly useful to us because it's a flexible way to build post-quantum secure ZKPs. MPCitH constructions build their security from symmetric-key primitives (like hash functions). This approach is also transparent, requiring no trusted setup. While STARKs share these post-quantum and transparent properties, MPCitH often offers faster prover times for many computations. Its primary trade-off, however, is that its proofs scale linearly with the size of the circuit to prove, while STARKs are succinct, meaning their proof size grows much slower.</p>
    <div>
      <h4>Rejection sampling</h4>
      <a href="#rejection-sampling">
        
      </a>
    </div>
    <p>When a randomness source is biased or outputs numbers outside the desired range, rejection sampling can correct the distribution. For example, imagine you need a random number between 1 and 10, but your computer only gives you random numbers between 0 and 255. (Indeed, this is the case!) The rejection sampling algorithm calls the RNG until it outputs a number below 11 and above 0: </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/ogslPSn4DJYx3R5jGZ3mi/7ab640864dc26d6e1e2eb53c25f628ea/image6.png" />
          </figure><p>Calling the generator over and over again may seem a bit wasteful. An efficient implementation can be realized with an eXtendable Output Function (XOF). A XOF takes an input, for example a seed, and computes an arbitrarily-long output. An example is the SHAKE family (part of the <a href="https://csrc.nist.gov/pubs/fips/202/final"><u>SHA3 standard</u></a>), and the recently proposed round-reduced version of SHAKE called <a href="https://datatracker.ietf.org/doc/rfc9861/"><u>TurboSHAKE</u></a>.</p><p>Let’s imagine you want to have three numbers between 1 and 10. Instead of calling the XOF over and over, you can also ask the XOF for several bytes of output. Since each byte has a probability of 3.52% to be in range, asking the XOF for 174 bytes is enough to have a greater than 99% chance of finding at least three usable numbers. In fact, we can be even smarter than this: 10 fits in four bits, so we can split the output bytes into lower and higher <a href="https://en.wikipedia.org/wiki/Nibble"><u>nibbles</u></a>. The probability of a nibble being in the desired range is now 56.4%:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4W98tjgA7gIkaM7A5LBMyi/7b12bbfd22e53b84439a7c9e690605d9/image2.png" />
          </figure><p><sup>Rejection sampling by batching queries. </sup></p><p>Rejection sampling is a part of many cryptographic primitives, including many we'll discuss in the schemes we look at below.</p>
    <div>
      <h3>Building post-quantum ACs</h3>
      <a href="#building-post-quantum-acs">
        
      </a>
    </div>
    <p>Classical anonymous credentials (ACs), such as ARC and ACT, are built from algebraic groups- specifically, elliptic curves, which are very efficient. Their security relies on the assumption that certain mathematical problems over these groups are computationally hard. The premise of post-quantum cryptography, however, is that quantum computers can solve these supposedly hard problems. The most intuitive solution is to replace elliptic curves with a post-quantum alternative. In fact, cryptographers have been working on a replacement for a number of years: <a href="https://eprint.iacr.org/2018/383"><u>CSIDH</u></a>. </p><p>This raises the key question: can we simply adapt a scheme like ARC by replacing its elliptic curves with CSIDH? The short answer is <b>no</b>, due to a critical roadblock in constructing the necessary zero-knowledge proofs. While we can, in theory, <a href="https://eprint.iacr.org/2023/1614"><u>build the required Sigma protocols or MPC-in-the-Head (MPCitH) proofs from CSIDH</u></a>, they have a prerequisite that makes them unusable in practice: they require a <b>trusted setup</b> to ensure the prover cannot cheat. This requirement is a non-starter, as <a href="https://eprint.iacr.org/2022/518"><u>no algorithm for performing a trusted setup in CSIDH exists</u></a>. The trusted setup for sigma protocols can be replaced by a combination of <a href="https://eprint.iacr.org/2016/505"><u>generic techniques from multi-party computation</u></a> and cut-and-choose protocols, but that adds significant computation cost to the already computationally expensive isogeny operations.</p><p>This specific difficulty highlights a more general principle. The high efficiency of classical credentials like ARC is deeply tied to the rich algebraic structure of elliptic curves. Swapping this component for a post-quantum alternative, or moving to generic constructions, fundamentally alters the design and its trade-offs. We must therefore accept that post-quantum anonymous credentials cannot be a simple "lift-and-shift" of today's schemes. They will require new designs built from different cryptographic primitives, such as lattices or hash functions.</p>
    <div>
      <h3>Prefabricated schemes from generic approaches</h3>
      <a href="#prefabricated-schemes-from-generic-approaches">
        
      </a>
    </div>
    <p>At Cloudflare, we explored a <a href="https://eprint.iacr.org/2023/414"><u>post-quantum privacy pass construction in 2023</u></a> that closely resembles the functionality needed for anonymous credentials. The main result is a generic construction that composes separate, quantum-secure building blocks: a digital signature scheme and a general-purpose ZKP system:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4dpmFzSv7HG5JHEEqu7D9o/ea1f02c37c0e36dc0972dfd1044fa9a3/image8.png" />
          </figure><p>The figure shows a cryptographic protocol divided into two main phases: (1.) Issuance: The user commits to a message (without revealing it) and sends the commitment to the server. The server signs the commitment and returns this signed commitment, which serves as a token. The user verifies the server's signature. (2.) Redemption: To use the token, the user presents it and constructs a proof. This proof demonstrates they have a valid signature on the commitment and opens the commitment to reveal the original message. If the server validates the proof, the user and server continue (e.g., to access a rate-limited origin).</p><p>The main appeal of this modular design is its flexibility. The experimental <a href="https://github.com/guruvamsi-policharla/zkdilithium"><u>implementation</u></a> uses a modified version of the signature ML-DSA signatures and STARKs, but the components can be easily swapped out. The design provides strong, composable security guarantees derived directly from the underlying parts. A significant speedup for the construction came from replacing the hash function SHA3 in ML-DSA with the zero-knowledge friendly <a href="https://eprint.iacr.org/2019/458"><u>Poseidon</u></a>.</p><p>However, the modularity of our post-quantum Privacy Pass construction <a href="https://zkdilithium.cloudflareresearch.com/index.html"><u>incurs a significant performance overhead</u></a> demonstrated in a clear trade-off between proof generation time and size: a fast 300 ms proof generation requires a large 173 kB signature, while a 4.8s proof generation time cuts the size of the signature nearly in half. A balanced parameter set, which serves as a good benchmark for any dedicated solution to beat, took 660 ms to sign and resulted in a 112 kB signature. The implementation is currently a proof of concept, with perhaps some room for optimization. Alternatively, a different signature like <a href="https://datatracker.ietf.org/doc/draft-ietf-cose-falcon/"><u>FN-DSA</u></a> could offer speed improvements: while its issuance is more complex, its verification is far more straightforward, boiling down to a simple hash-to-lattice computation and a norm check.</p><p>However, while this construction gives a functional baseline, these figures highlight the performance limitations for a real-time rate limiting system, where every millisecond counts. The 660 ms signing time strongly motivates the development of <i>dedicated</i> cryptographic constructions that trade some of the modularity for performance.</p>
    <div>
      <h3>Solid structure: Lattices</h3>
      <a href="#solid-structure-lattices">
        
      </a>
    </div>
    <p><a href="https://blog.cloudflare.com/lattice-crypto-primer/"><u>Lattices</u></a> are a natural starting point when discussing potential post-quantum AC candidates. NIST standardized ML-DSA and ML-KEM as signature and KEM algorithms, both of which are based on lattices. So, are lattices the answer to post-quantum anonymous credentials?</p><p>The answer is a bit nuanced. While explicit anonymous credential schemes from lattices exist, they have shortcomings that prevent real-world deployment: for example, a <a href="https://eprint.iacr.org/2023/560.pdf"><u>recent scheme</u></a> sacrifices round-optimality for smaller communication size, which is unacceptable for a service like Privacy Pass where every second counts. Given that our RTT is 100ms or less for the majority of users, each extra communication round adds tangible latency especially for those on slower Internet connections. When the final credential size is still over 100 kB, the trade-offs are hard to justify. So, our search continues. We expand our horizon by looking into <i>blind signatures </i>and whether we can adapt them for anonymous credentials.</p>
    <div>
      <h4>Two-step approach: Hash-and-sign</h4>
      <a href="#two-step-approach-hash-and-sign">
        
      </a>
    </div>
    <p>A prominent paradigm in lattice-based signatures is the <i>hash-and-sign</i> construction. Here, the message is first hashed to a point in the lattice. Then, the signer uses their secret key, a <a href="https://eprint.iacr.org/2007/432"><u>lattice trapdoor</u></a>, to generate a vector that, when multiplied with the private key, evaluates to the hashed point in the lattice. This is the core mechanism behind signature schemes like FN-DSA.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/66hA0KmluGoGO4I2SHAGTv/1a465c6c810e4f17df3112b96ed816da/image1.png" />
          </figure><p>Adapting hash-and-sign for blind signatures is tricky, since the signer may not learn the message. This introduces a significant security challenge: If the user can request signatures on arbitrary points, they can mount an attack to extract the trapdoor by repeatedly requesting signatures for carefully chosen arbitrary points. These points can be used to reconstruct a short basis, which is equivalent to a key recovery. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1lyCHqOTL477mFGSWjH3dv/48ffe46acfbe81b692c2ba30f383634b/image9.png" />
          </figure><p>The standard defense against this attack is to require the user to prove in zero-knowledge that the point they are asking to be signed is the blinded output of the specified hash function. However, proving hash preimages leads to the same problem as in the generic post-quantum privacy pass paper: proving a conventional hash function (like SHA3) inside a ZKP is computationally expensive and has a large communication complexity.</p><p>This difficult trade-off is at the heart of recent academic work. The <a href="https://eprint.iacr.org/2023/077.pdf"><u>state-of-the-art paper</u></a> presents two lattice-based blind signature schemes with small signature sizes of 22 KB for a signature and 48 kB for a privately-verifiable protocol that may be more useful in a setting like anonymous credential. However, this focus on the final signature size comes at the cost of an impractical <i>issuance</i>. The user must provide ZKPs for the correct hash and lattice relations that, by the paper’s own analysis, can add to<i> several hundred kilobytes</i> and take<i> 20 seconds to generate and 10 seconds to verify</i>.</p><p>While these results are valuable for advancing the field, this trade-off is a significant barrier for any large-scale, practical system. For our use case, a protocol that increases the final signature size moderately in exchange for a more efficient and lightweight issuance process would be a more suitable and promising direction.</p>
    <div>
      <h4>Best of two signatures: Hash-and-sign with aborts</h4>
      <a href="#best-of-two-signatures-hash-and-sign-with-aborts">
        
      </a>
    </div>
    <p>A promising technique for blind signatures combines the hash-and-sign paradigm with <i>Fiat-Shamir with aborts</i>, a method that relies on rejection sampling signatures. In this approach, the signer repeatedly attempts to generate a signature and aborts any result that may leak information about the secret key. This process ensures the final signature is statistically independent of the key and is used in modern signatures like ML-DSA. The <a href="https://eprint.iacr.org/2014/1027"><u>Phoenix signature</u></a> scheme uses <i>hash-and-sign with aborts</i>, where a message is first hashed into the lattice and signed, with rejection sampling employed to break the dependency between the signature and the private key.</p><p>Building on this foundation is an <a href="https://eprint.iacr.org/2024/131"><u>anonymous credential scheme for hash-and-sign with aborts</u></a>. The main improvement over hash-and-sign anonymous credentials is that, instead of proving the validity of a hash, the user commits to their attributes, which avoids costly zero-knowledge proofs.</p><p>The scheme is <a href="https://github.com/Chair-for-Security-Engineering/lattice-anonymous-credentials"><u>fully implemented</u></a> and credentials with attribute proofs just under 80 KB and signatures under 7 kB. The scheme takes less than 400 ms for issuance and 500 ms for showing the credential. The protocol also has a lot of features necessary for anonymous credentials, allowing users to prove relations between attributes and request pseudonyms for different instances.</p><p>This research presents a compelling step towards real-world deployability by combining state-of-the-art techniques to achieve a much healthier balance between performance and security. While the underlying mathematics are a bit more complex, the scheme is fully implemented and with a proof of knowledge of a signature at 40 kB and a prover time under a second, the scheme stands out as a great contender. However, for practical deployment, these figures would likely need a significant speedup to be usable in real-time systems. An improvement seems plausible, given recent <a href="https://eprint.iacr.org/2024/1952"><u>advances in lattice samplers</u></a>. Though the exact scale we can achieve is unclear. Still, we think it would be worthwhile to nudge the underlying design paradigm a little closer to our use cases.</p>
    <div>
      <h3>Do it yourself: MPC-in-the-head </h3>
      <a href="#do-it-yourself-mpc-in-the-head">
        
      </a>
    </div>
    <p>While the lattice-based hash-and-sign with aborts scheme provides one path to post-quantum signatures, an alternative approach is emerging from the MPCitH variant VOLE-in-the-Head <a href="https://eprint.iacr.org/2023/996"><u>(VOLEitH)</u></a>. </p><p>This scheme builds on <a href="https://eprint.iacr.org/2017/617"><u>Vector Oblivious Linear Evaluation (VOLE)</u></a>, an interactive protocol where one party's input vector is processed with another's secret value <i>delta</i>, creating a <i>correlation</i>. This VOLE correlation is used as a cryptographic commitment to the prover’s input. The system provides a zero-knowledge proof because the prover is bound by this correlation and cannot forge a solution without knowing the secret delta. The verifier, in turn, just has to verify that the final equation holds when the commitment is opened. This system is <i>linearly homomorphic</i>, which means that two commitments can be combined. This property is ideal for the <i>commit-and-prove</i> paradigm, where the prover first commits to the witnesses and then proves the validity of the circuit gate by gate. The primary trade-off is that the proofs are linear in the size of the circuit, but they offer substantially better runtimes. We also use linear-sized proofs for ARC and ACT.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6o073F0y7J7RxxHuDb4BSY/1ac0c4fc8b154dd77a8d3294016cbd32/image4.png" />
          </figure><p><sup>Example of evaluating a circuit gate by first committing to each wire and then proving the composition. This is easy for linear gates.</sup></p><p>This commit-and-prove approach allows <a href="https://link.springer.com/chapter/10.1007/978-3-031-91134-7_14"><u>VOLEitH</u></a> to efficiently prove the evaluation of symmetric ciphers, which are quantum-resistant. The transformation to a non-interactive protocol follows the standard MPCitH method: the prover commits to all secret values, a challenge is used to select a subset to reveal, and the prover proves consistency.</p><p>Efficient implementations operate over two mathematical fields (binary and prime) simultaneously, allowing these ZK circuits to handle both arithmetic and bitwise functions (like XORs) efficiently. Based on this foundation, a <a href="https://www.youtube.com/watch?v=VMeaF9xgbcw"><u>recent talk</u></a> teased the potential for blind signatures from the multivariate quadratic signature scheme <a href="https://pqmayo.org/about/"><u>MAYO</u></a> with sizes of just 7.5 kB and signing/verification times under 50 ms.</p><p>The VOLEitH approach, as a general-purpose solution system, represents a promising new direction for performant constructions. There are a <a href="https://pqc-mirath.org"><u>number</u></a> <a href="https://mqom.org"><u>of</u></a> <a href="https://pqc-perk.org"><u>competing</u></a> <a href="https://sdith.org"><u>in-the-head</u></a> schemes in the <a href="https://csrc.nist.gov/projects/pqc-dig-sig"><u>NIST competition for additional signature schemes</u></a>, including <a href="https://faest.info/authors.html"><u>one based on VOLEitH</u></a>. The current VOLEitH literature focuses on high-performance digital signatures, and an explicit construction for a full anonymous credential system has not yet been proposed. This means that features standard to ACs, such as multi-show unlinkability or the ability to prove relations between attributes, are not yet part of the design, whereas they are explicitly supported by the lattice construction. However, the preliminary results show great potential for performance, and it will be interesting to see the continued cryptanalysis and feature development from this line of VOLEitH in the area of anonymous credentials, especially since the general-purpose construction allows adding features easily.
</p><table><tr><td><p><b>Approach</b></p></td><td><p><b>Pros</b></p></td><td><p><b>Cons</b></p></td><td><p><b>Practical Viability</b></p></td></tr><tr><td><p><a href="https://eprint.iacr.org/2023/414"><u>Generic Composition</u></a></p></td><td><p>Flexible construction, strong security</p></td><td><p>Large signatures (112 kB), slow (660 ms)</p></td><td><p>Low: Performance is not great</p></td></tr><tr><td><p><a href="https://eprint.iacr.org/2023/077.pdf"><u>Hash-and-sign</u></a></p></td><td><p>Potentially tiny signatures, lots of optimization potential</p></td><td><p>Current implementation large and slow</p></td><td><p>Low: Performance is not great</p></td></tr><tr><td><p><a href="https://eprint.iacr.org/2024/131"><u>Hash-and-sign with aborts</u></a></p></td><td><p>Full AC system, good balance in communication</p></td><td><p>Slow runtimes (1s)</p></td><td><p>Medium: promising but performance would need to improve</p></td></tr><tr><td><p><a href="https://www.youtube.com/watch?v=VMeaF9xgbcw"><u>VOLEitH</u></a></p></td><td><p>Excellent potential performance (&lt;50ms, 7.5 kB)</p></td><td><p>not a full AC system, not peer-reviewed</p></td><td><p>Medium: promising research direction, no full solution available so far</p></td></tr></table>
    <div>
      <h2>Closing the gap</h2>
      <a href="#closing-the-gap">
        
      </a>
    </div>
    <p>My (that is Lena's) internship focused on a critical question: what should we look at next to build ACs for the Internet? For us, "the right direction" means developing protocols that can be integrated with real world applications, and developed collaboratively at the IETF. To make these a reality, we need researchers to look beyond blind signatures; we need a complete privacy-preserving protocol that combines blind signatures with efficient zero-knowledge proofs and properties like multi-show credentials that have an internal state. The issuance should also be sublinear in communication size with the number of presentations.</p><p>So, with the transition to post-quantum cryptography on the horizon, what are our thoughts on the current IETF proposals? A 2022 NIST presentation on the current state of anonymous credentials states that <a href="https://csrc.nist.gov/csrc/media/Presentations/2022/stppa4-revoc-decent/images-media/20221121-stppa4--baldimtsi--anon-credentials-revoc-decentral.pdf"><u>efficient post-quantum secure solutions are basically non-existent</u></a>. We argue that the last three years show nice developments in lattices and MPCitH anonymous credentials, but efficient post-quantum protocols still need work. Moving protocols into a post-quantum world isn't just a matter of swapping out old algorithms for new ones. A common approach on constructing post-quantum versions of classical protocols is swapping out the building blocks for their quantum-secure counterpart. </p><p>We believe this approach is essential, but not forward-looking. In addition to identifying how modern concerns can be accommodated on old cryptographic designs, we should be building new, post-quantum native protocols.</p><ul><li><p>For ARC, the conceptual path to a post-quantum construction seems relatively straightforward. The underlying cryptography follows a similar structure as the lattice-based anonymous credentials, or, when accepting a protocol with fewer features, the <a href="https://eprint.iacr.org/2023/414"><u>generic post-quantum privacy-pass</u></a> construction. However, we need to support per-origin rate-limiting, which allows us to transform a token at an origin without leaking us being able to link the redemption to redemptions at other origins, a feature that none of the post-quantum anonymous credential protocols or blind signatures support. Also, ARC is sublinear in communication size with respect to the number of tokens issued, which so far only the hash-and-sign with abort lattices achieve, although the notion of “limited shows” is not present in the current proposal. In addition, it would be great to gauge efficient implementations, especially for blind signatures, as well as looking into efficient zero-knowledge proofs. </p></li><li><p>For ACT, we need the protocols for ARC and an additional state. Even for the simplest counter, we need the ability to homomorphically subtract from that balance within the credential itself. This is a much more complex cryptographic requirement. It would also be interesting to see a post-quantum double-spend prevention that enforces the sequential nature of ACT. </p></li></ul><p>Working on ACs and other privacy-preserving cryptography inevitably leads to a major bottleneck: efficient zero-knowledge proofs, or to be more exact, efficiently proving hash function evaluations. In a ZK circuit, multiplications are expensive. Each wire in the circuit that performs a multiplication requires a cryptographic commitment, which adds communication overhead. In contrast, other operations like XOR can be virtually "free." This makes a huge difference in performance. For example, SHAKE (the primitive used in ML-DSA) can be orders of magnitude slower than arithmetization-friendly hash functions inside a ZKP. This is why researchers and implementers are already using <a href="https://eprint.iacr.org/2019/458"><u>Poseidon</u></a> or <a href="https://eprint.iacr.org/2023/323"><u>Poseidon2</u></a> to make their protocols faster.</p><p>Currently, <a href="https://www.poseidon-initiative.info/"><u>Ethereum</u></a> is <a href="https://x.com/VitalikButerin/status/1894681713613164888"><u>seriously considering migrating Ethereum to the Poseidon hash</u></a> and calls for cryptanalysis, but there is no indication of standardization. This is a problem: papers increasingly use different instantiations of Poseidon to fit their use-case, and there <a href="https://eprint.iacr.org/2016/492"><u>are</u></a> <a href="https://eprint.iacr.org/2023/323"><u>more</u></a> <a href="https://eprint.iacr.org/2022/840"><u>and</u></a> <a href="https://eprint.iacr.org/2025/1893"><u>more</u></a> <a href="https://eprint.iacr.org/2025/926"><u>zero</u></a>-<a href="https://eprint.iacr.org/2020/1143"><u>knowledge</u></a> <a href="https://eprint.iacr.org/2019/426"><u>friendly</u></a> <a href="https://eprint.iacr.org/2023/1025"><u>hash</u></a> <a href="https://eprint.iacr.org/2021/1038"><u>functions</u></a> <a href="https://eprint.iacr.org/2022/403"><u>coming</u></a> <a href="https://eprint.iacr.org/2025/058"><u>out</u></a>, tailored to different use-cases. We would like to see at least one XOF and one hash each for a prime field and for a binary field, ideally with some security levels. And also, is Poseidon the best or just the most well-known ZK friendly cipher? Is it always secure against quantum computers (like we believe AES to be), and are there other attacks like the <a href="https://eprint.iacr.org/2025/950"><u>recent</u></a> <a href="https://eprint.iacr.org/2025/937"><u>attacks</u></a> on round-reduced versions?</p><p>Looking at algebra and zero-knowledge brings us to a fundamental debate in modern cryptography. Imagine a line representing the spectrum of research: On one end, you have protocols built on very well-analyzed standard assumptions like the <a href="https://blog.cloudflare.com/lattice-crypto-primer/#breaking-lattice-cryptography-by-finding-short-vectors"><u>SIS problem</u></a> on lattices or the collision resistance of SHA3. On the other end, you have protocols that gain massive efficiency by using more algebraic structure, which in turn relies on newer, stronger cryptographic assumptions. Breaking novel hash functions is somewhere in the middle. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2BMtbDoVnrmKeTvhCyfOjK/616438127351eedf6ff41db282a0511e/image7.png" />
          </figure><p>The answer for the Internet can’t just be to relent and stay at the left end of our graph to be safe. For the ecosystem to move forward, we need to have confidence in both. We need more research to validate the security of ZK-friendly primitives like Poseidon, and we need more scrutiny on the stronger assumptions that enable efficient algebraic methods.</p>
    <div>
      <h2>Conclusion</h2>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>As we’ve explored, the cryptographic properties that make classical ACs efficient, particularly the rich structure of elliptic curves, do not have direct post-quantum equivalents. Our survey of the state of the art from generic compositions using STARKs, to various lattice-based schemes, and promising new directions like MPC-in-the-head, reveals a field full of potential but with no clear winner. The trade-offs between communication cost, computational cost, and protocol rounds remain a significant barrier to practical, large-scale deployment, especially in comparison to elliptic curve constructions.</p><p>To bridge this gap, we must move beyond simply building post-quantum blind signatures. We challenge our colleagues in academia and industry to develop complete, post-quantum native protocols that address real-world needs. This includes supporting essential features like the per-origin rate-limiting required for ARC or the complex stateful credentials needed for ACT.</p><p>A critical bottleneck for all these approaches is the lack of efficient, standardized, and well-analyzed zero-knowledge-friendly hash functions. We need to research zero-knowledge friendly primitives and build industry-wide confidence to enable efficient post-quantum privacy.</p><p>If you’re working on these problems, or you have experience in the management and deployment of classical credentials, now is the time to engage. The world is rapidly adopting credentials for everything from digital identity to bot management, and it is our collective responsibility to ensure these systems are private and secure for a post-quantum future. We can tell for certain that there are more discussions to be had, and if you’re interested in helping to build this more secure and private digital world, we’re hiring 1,111 interns over the course of next year, and have open positions!</p> ]]></content:encoded>
            <category><![CDATA[AI Bots]]></category>
            <category><![CDATA[Post-Quantum]]></category>
            <category><![CDATA[IETF]]></category>
            <category><![CDATA[European Union]]></category>
            <category><![CDATA[Elliptic Curves]]></category>
            <category><![CDATA[Cryptography]]></category>
            <guid isPermaLink="false">JA04hlqr6TaeGhkvyutbt</guid>
            <dc:creator>Lena Heimberger</dc:creator>
            <dc:creator>Christopher Patton</dc:creator>
        </item>
    </channel>
</rss>