This would definitely seem like a big concern if you were just looking at the RFC, but the key here is that Kagi's system has a different set of security/privacy/functional requirements and therefore the issues mentioned in the RFC do not necessarily apply.
In the RFC's architecture, the request flow is like so:
1. CLIENT sends anonymous request to ORIGIN
2. ORIGIN sends token challenge to CLIENT
3. CLIENT uses its identity to request token from ISSUER/ATTESTER
4. ISSUER/ATTESTER issues token to CLIENT
5. CLIENT sends token to ORIGIN
You can see how the ISSUER/ATTESTER can identify the client as the source of the "anonymous request" to the ORIGIN because the ISSUER, ATTESTER and ORIGIN are the same entity, so it can use a timing attack to correlate the request to the ORIGIN (1.) with the request to the ISSUER/ATTESTER (3.).
However you can also see that if a lot of time passes between steps (1.) and (3.), then such an attack would be infeasible. Reading past your quote from RFC 9576 § 4.1., it states:
> Origin-Client, Issuer-Client, and Attester-Origin unlinkability requires that issuance and redemption events be separated over time, such as through the use of tokens that correspond to token challenges with an empty redemption context (see Section 3.4), or that they be separated over space, such as through the use of an anonymizing service when connecting to the Origin.
In Kagi's architecture, the "time separation" requirement is met by making the client generate a large batch of tokens up front, which are then slowly redeemed over a period of 2 months. The "space separation" requirement is also satisfied with the introduction of the Tor service.
There is some more discussion in RFC 9576 § 7.1. "Token Caching" and RFC 9577 § 5.5. "Timing Correlation Attacks".
One question you may have is: Why wasn't this solution used in the RFC?
This can be understood if you look at the mentions of "cross-ORIGIN" in the RFC. This RFC was written by Cloudflare, who envisioned it's use across the whole Internet. Different ORIGINs would trust different ISSUERs, tokens from one ORIGIN<->ISSUER network might not work in another ORIGIN<->ISSUER network. This made it infeasible for clients to mass-generate tokens in advance, as a client would need to generate tokens across many different ISSUERS.
Of course, adoption was weak and there ended up being only one ISSUER - Cloudflare, so they adopted the same architecture as Kagi where clients would batch generate tokens in advance (batch size was only 30 tokens though).
RFC 9576 § 7.1. also mentions a "token hoarding" attack, which Cloudflare felt particularly threatened by. Cloudflare's Privacy Pass system worked in concert with CAPTCHAs. Users could trade a completed CAPTCHA for a small batch of tokens, allowing a single CAPTCHA completion to be split into multiple redemptions across a longer time period.
However, rudimentary "hoarding"-like attacks were already in use against CAPTCHAs through "traffic exchanges". Opening up another avenue for hoarding through Privacy Pass would have only exacerbated the problem.
>3. CLIENT uses it's identity to request token from ISSUER/ATTESTER
The ISSUER and ATTESTER are different roles. As previously quoted, "Clients explicitly trust Attesters to perform attestation correctly and in a way that does not violate their privacy." The RFC is explicit that, when all of the roles are held by the same entity, the attestation should not rely on unique identifiers. But that's exactly what a session cookie is.
>You can see how the ISSUER/ATTESTER can identify the client as the source of the "anonymous request" to the ORIGIN because the ISSUER, ATTESTER and ORIGIN are the same entity, and therefore it can use a timing attack to correlate the request to the ORIGIN (1.) with the request to the ISSUER/ATTESTER (3.).
No timing or spacing attack is needed here. If I have to provide Kagi with a valid session cookie in order to get the tokens, then they already have a unique identifier for me. There is no guarantee that Kagi is not keeping a 1-to-1 mapping of session cookies to ISSUER keypairs, or that Kagi could not, if compelled, establish distinct ISSUER keypairs for specific session cookies.
> The RFC is explicit that, when all of the roles are held by the same entity, the attestation should not rely on unique identifiers. But that's exactly what a session cookie is.
Very true, but again, the RFC describes a completely different threat model with much stronger guarantees. The Kagi threat model:
- Does not provide Issuer-Client unlinkability
- Does not provide Attester-Origin unlinkability
In particular, the model does not assume a malicious Issuer and requires the Client have some level of trust in the Issuer. The Client trusts the Issuer with their private billing information but does not trust the Issuer with their search activity.
The RFC explicitly guarantees the Issuer cannot obtain any of the Client's private information.
That said, I will point out that this Issuer-Client unlinkability issue can be solved by introducing a 3rd-party service or when Kagi starts accepting Monero payments.
> There is no guarantee that Kagi is not keeping a 1-to-1 mapping of session cookies to ISSUER keypairs, or that Kagi could not, if compelled, establish distinct ISSUER keypairs for specific session cookies.
Also completely valid, but also not something Kagi claims to guarantee. They believe the extension should be responsible for guarding attainer issuance partitioning. I don't think it's implemented currently but it shouldn't be too hard, especially since they currently use only 1 keypair.
>Very true, but again, the RFC describes a completely different threat model with much stronger guarantees. The Kagi threat model:
>
>- Does not provide Issuer-Client unlinkability
>
>- Does not provide Attester-Origin unlinkability
If the Client, Attester, and Origin are all a single party (Kagi), then it follows from that threat model that Kagi does not provide Kagi-Client unlinkability, no?
Further, this is not what Kagi has advertised in the blog post:
>What guarantees does Privacy Pass offer?
>
>As used by Kagi, Privacy Pass tokens offer various security properties (§ 3.3, of [2]).
Kagi are explicitly stating that they provide the guarantees of § 3.3. They even use more plain language:
>Generation-redemption unlinkability: Kagi cannot link the tokens presented during token redemption (i.e. during search) with any specific token generation phase. *This means that Kagi will not be able to tell who it is serving search results to*, only that it is someone who presented a valid Privacy Pass token.
>
>Redemption-redemption unlinkability: Kagi cannot link the tokens presented during two different token redemptions. This means that *Kagi will not be able to tell from tokens alone whether two searches are being performed by the same user*.
As it stands, Kagi cannot meaningfully guarantee those things, because the starting point is the client providing a unique identifier to Kagi.
>That said, I will point out that this Issuer-Client unlinkability issue can be solved by introducing a 3rd-party service or when Kagi starts accepting Monero payments.
Sure, but at that point, there is no need for any of the Privacy Pass infrastructure in the first place.
>Also completely valid, but also not something Kagi claims to guarantee.
I disagree. Their marketing here is "we can't link your searches to your identity, because cryptography."
>They believe the extension should be responsible for guarding attainer issuance partitioning. I don't think it's implemented currently but it shouldn't be too hard, especially since they currently use only 1 keypair.
If Kagi is going to insist on being the attester and on requiring uniquely identifiable information as the basis for issuing tokens, then yes, the only way to even try to confirm that they're not acting maliciously is to keep track not only of distinct keypairs, but also of public and private metadata blocks within the tokens, and to share all of that data (in a trustworthy manner, of course) with other confirmed Kagi users. And if a user doesn't understand all of the nuances that would entail, or all of the nuances just discussed here, and instead just trusts the Kagi-written client implicitly? Then it's all just privacy theater.
> If the Client, Attester, and Origin are all a single party (Kagi), then it follows from that threat model that Kagi does not provide Kagi-Client unlinkability, no?
Kagi does not provide Kagi-Client unlinkability as the Client's payment information allows Kagi to trivially determine the identity of the Client. Kagi does provide Search-Client unlinkability (what the RFC calls Origin-Client unlinkability). More formally: If we assume Kagi cannot derive any identifying information from the privacy token (which I understand you dispute), then given any two incoming search requests, Kagi would not be able to determine whether those two requests came from the same Client or two different Clients.
> Kagi are explicitly stating that they provide the guarantees of § 3.3. They even use more plain language:
Not 100% sure I am understanding you correctly but if you are claiming that Kagi promises all the unlinkability properties in § 3.3, I would say that would be unfair, since they explicitly deny this in the FAQ at the bottom of the post.
I think they are citing that section as they reference several definitions from it in the text that follows.
> >Generation-redemption unlinkability: Kagi cannot link the tokens presented during token redemption (i.e. during search) with any specific token generation phase. *This means that Kagi will not be able to tell who it is serving search results to*, only that it is someone who presented a valid Privacy Pass token. > >Redemption-redemption unlinkability: Kagi cannot link the tokens presented during two different token redemptions. This means that *Kagi will not be able to tell from tokens alone whether two searches are being performed by the same user*.
>
> As it stands, Kagi cannot meaningfully guarantee those things, because the starting point is the client providing a unique identifier to Kagi.
These specific unlinkability properties are satisfied given that the earlier assumption about the token not providing identifiable information is true.
> Sure, but at that point, there is no need for any of the Privacy Pass infrastructure in the first place.
Kagi Privacy Pass in combination with a 3rd party can acheive a level of privacy that cannot be matched by architectures that don't involve the Privacy Pass or some other exotic cryptography.
I claim that a 3rd-party service + Kagi Privacy Pass meets all unlinkability properties in the RFC (except Attester-Origin for obvious reasons). Additionally, it guarantees confidentiality of the search request and response from malicious middleboxes, given the assumption about the token is true and that the user has access to a trusted proxy.
> I disagree. Their marketing here is "we can't link your searches to your identity, because cryptography."
Disagreement acknowledged. And yes, that quote is a fairly accurate summary of the marketing!
> If Kagi is going to insist on being the attester and on requiring uniquely identifiable information as the basis for issuing tokens, then yes, the only way to even try to confirm that they're not acting maliciously is to keep track not only of distinct keypairs, but also of public and private metadata blocks within the tokens, and to share all of that data (in a trustworthy manner, of course) with other confirmed Kagi users. And if a user doesn't understand all of the nuances that would entail, or all of the nuances just discussed here, and instead just trusts the Kagi-written client implicitly? Then it's all just privacy theater.
Yeah, I'm glad you are willing to say it at least, a lot of stuff these days is security theatre, people just kinda stick their heads in the sand I guess? I'm still hoping that people will realize that SSL has been long in need of a successor, and frankly BGP needs a complete rework too. It's also surprising to me that people are still willing to use Linux distros, although realistically modern computing as a whole is rotten at it's core. At least PGP is still alive, but it has its problems too...
In the RFC's architecture, the request flow is like so:
1. CLIENT sends anonymous request to ORIGIN
2. ORIGIN sends token challenge to CLIENT
3. CLIENT uses its identity to request token from ISSUER/ATTESTER
4. ISSUER/ATTESTER issues token to CLIENT
5. CLIENT sends token to ORIGIN
You can see how the ISSUER/ATTESTER can identify the client as the source of the "anonymous request" to the ORIGIN because the ISSUER, ATTESTER and ORIGIN are the same entity, so it can use a timing attack to correlate the request to the ORIGIN (1.) with the request to the ISSUER/ATTESTER (3.).
However you can also see that if a lot of time passes between steps (1.) and (3.), then such an attack would be infeasible. Reading past your quote from RFC 9576 § 4.1., it states:
> Origin-Client, Issuer-Client, and Attester-Origin unlinkability requires that issuance and redemption events be separated over time, such as through the use of tokens that correspond to token challenges with an empty redemption context (see Section 3.4), or that they be separated over space, such as through the use of an anonymizing service when connecting to the Origin.
In Kagi's architecture, the "time separation" requirement is met by making the client generate a large batch of tokens up front, which are then slowly redeemed over a period of 2 months. The "space separation" requirement is also satisfied with the introduction of the Tor service.
There is some more discussion in RFC 9576 § 7.1. "Token Caching" and RFC 9577 § 5.5. "Timing Correlation Attacks".
One question you may have is: Why wasn't this solution used in the RFC?
This can be understood if you look at the mentions of "cross-ORIGIN" in the RFC. This RFC was written by Cloudflare, who envisioned it's use across the whole Internet. Different ORIGINs would trust different ISSUERs, tokens from one ORIGIN<->ISSUER network might not work in another ORIGIN<->ISSUER network. This made it infeasible for clients to mass-generate tokens in advance, as a client would need to generate tokens across many different ISSUERS.
Of course, adoption was weak and there ended up being only one ISSUER - Cloudflare, so they adopted the same architecture as Kagi where clients would batch generate tokens in advance (batch size was only 30 tokens though).
RFC 9576 § 7.1. also mentions a "token hoarding" attack, which Cloudflare felt particularly threatened by. Cloudflare's Privacy Pass system worked in concert with CAPTCHAs. Users could trade a completed CAPTCHA for a small batch of tokens, allowing a single CAPTCHA completion to be split into multiple redemptions across a longer time period.
However, rudimentary "hoarding"-like attacks were already in use against CAPTCHAs through "traffic exchanges". Opening up another avenue for hoarding through Privacy Pass would have only exacerbated the problem.