So....is this privacy through assumed lack of logging? Not trying to be a dick, just legit don't understand a part of this.
User A asks kagi for tokens. Kagi says "sure, here's 500 tokens". If kagi then logs the 500 tokens it just gave to user A, it now will know if any of those tokens is redeemed at a later date, that they're assigned to user A?
Of course if Kagi just doesn't retain this data, then yeah all is good because the token itself is only marked as valid, not valid and given to user A on date Y, but....that's it right? Or am I misunderstanding something?
The server does not generate the tokens, the client generates the tokens. The server is supposed to be able to verify that they were generated by a client who was granted the authority to generate them, but not which client did so. At least, not without side-channel information.
> The main building block of our construction is a verifiable oblivious pseudorandom function (VOPRF)
I am not sure how well tested that primitive is, but it definitely appears to be more than the server handing clients tokens and then pretending not to know who it gave them to.
What I find confusing is: Given that the server is essentially authorizing each subsequent client request (eg: For Kagi: search queries after a Kagi user has already been authenticated) in a way whereby the client is anonymous, what is the difference between Privacy Pass and simply providing a common authorization token to each user (and thus skipping all this cryptography)?
Update: On some thought, for the approach of the server providing a common authorization token that there is no guarantee to the client that the server is actually providing a common token and thus not just simply providing a unique identifier to each user. Thus, the Privacy Pass's cryptography ensures that the client knows that it is still anonymous. Update 2: But, what guarantee exists that the server doesn't generate a unique public key (i.e. public-private key pair) for each user and thus defeat anonymity this way? Update 3: They use zero-knowledge proofs to prove that all tokens are signed by the same private-key, from their paper: "The work of Jarecki et al. [18] uses a non-interactive zero-knowledge (NIZK) proof of discrete log equality (DLEQ) to provide verification of the OPRF result to the user. Their construction is hence a ‘verifiable’ OPRF or VOPRF and is proven secure in the random-oracle model. We adapt their construction slightly to use a ‘batch’ DLEQ proof allowing for much more efficient verification; in short this allows a user to verify a single NIZK proof that states that all of their tokens are signed by the same private key. This prevents the edge from using different key pairs for different users in an attempt to launch a deanonymization attack; we give more details in Section 3.2.".
Privacy Pass docs [0] cover this, but it is mostly referenced deeper in the paper. I believe the idea is that the tokens returned by the server are "unlinkable" to the (modified) tokens passed back by the client. So the server knows it passed back tokens A, B and C to some users, and later receives tokens X, Y and Z. It knows that X, Y and Z are valid, but not their correspondance to the tokens it issued. It uses elliptic curve cryptography for this.
After reading your comment I still didn't quite understand how the server couldn't just simply log the tokens A, B, C issued to user X. So I had a look at the website you linked: IIUC the key is that the tokens are actually generated by the user and the server never sees them (unblinded) before their first usage:
> When an internet challenge is solved correctly by a user, Privacy Pass will generate a number of random nonces that will be used as tokens. These tokens will be cryptographically blinded and then sent to the challenge provider. If the solution is valid, the provider will sign the blinded tokens and return them to the client. Privacy Pass will unblind the tokens and store them for future use.
> Privacy Pass will detect when an internet challenge is required in the future for the same provider. In these cases, an unblinded, signed token will be embedded into a privacy pass that will be sent to the challenge provider. The provider will verify the signature on the unblinded token, if this check passes the challenge will not be invoked.
> the tokens are actually generated by the user and the server never sees them (unblinded) before their first usage
Here is how I see it:
1. The user generates a token/nonce => T
2. The user blinds the token with secret blinding factor b => Blinded token TB = T*b
3. The user sends the blinded token for signing. The server signs it and returns it to the user => Signed blinded token TBS = Sign(TB)
4. The user unblinds the token (this does not break the signature) => Signed Unblinded token TS = TBS/b
5. The user sends TS for its search query.
The server signed TB, then received TS. Even if it logged that TB = user, it cannot link TS to TB, because it does not know the blinding factor b. Thus, it cannot link the search query with TS to the user.
Ah thank you. That's the part I was missing. I know this example is wrong in 100 different ways, but something like "yeah we know a key with prime factor X is valid, and this has one", but there's thousands of those out there, so it can't tie out to whom.
User A asks kagi for tokens. Kagi says "sure, here's 500 tokens". If kagi then logs the 500 tokens it just gave to user A, it now will know if any of those tokens is redeemed at a later date, that they're assigned to user A?
Of course if Kagi just doesn't retain this data, then yeah all is good because the token itself is only marked as valid, not valid and given to user A on date Y, but....that's it right? Or am I misunderstanding something?