Nick Mathewson nickm@torproject.org writes:
[ text/plain ] Hi! I thought I'd write this up while it was fresh in my mind. It could be used as an alternative method to the current proposed client authentication mechanism. We could implement both, or just this, or just the other.
My description here will be a bit terser than we'd want in a proper proposal, but I wanted to share it.
This design is based on George Kadianakis's client authentication design; it won't make sense unless you've read it.
=============
Let every client generate a curve25519 keypair, and tell the hidden service operator about the public key. This keypair takes the place of the long-term shared secret. For some client C, denote the secret key as x_X and the public key as X_C.
For every descriptor, the hidden service generates a fresh keypair <y, Y>, and includes Y in the the outer encrypted layer.
Now, for each client, the hidden service computes curve25519(X_C, y) and uses this as the input for two KDF functions. Call these outputs K1_C and K2_C. The hidden service generates an auth-client line for each client as follows:
"auth-client" SP client-id SP encrypted-cookie
This is the same as in George's proposal, except that client-id is derived from a truncated version of K1_C, and the encrypted-cookie portion is encrypted based on K2_C.
When the client receives the descriptor, it decrypts the outer layer, then sees the value of Y that the hidden server advertised. It computes curve25519(Y, x_c), and derives K1_C and K2_C. It uses K1_C to find the appropriate entry on the list, and then uses K2_C to decrypt it and find the descriptor cookie.
=============
Advantages:
- managing public keys can be easier than managing shared secrets.
- The encoding is slightly shorter, since no IV is needed, since K2
is different every time.
- probably others?
Disadvantages:
- Curve25519 costs more computationally than non-public-key operations
- probably others?
Hey Nick,
thanks for the feedback on the torspec patch and this scheme. I'll wait to figure out if we want to use this scheme before updating the torspec patch further.
This proposed scheme seems like a good idea. It basically switches the identity of authed clients from symmetric keys to x25519 keys, which seems more intuitive and correct.
I wonder if clients could/should use the same keypair for intro-layer authentication as well. Section 3.4.2 currently specifies how to do intro-layer auth using ed25519 keys, so perhaps we can use a single curve25519 key (and switch it between ed25519 and x25519) to perform both descriptor-layer and intro-layer authentication?
WRT the suggested scheme, I think my biggest concern here is the UX, and specifically this phrase
"Let every client generate a curve25519 keypair, and tell the hidden service operator about the public key".
The client auth UX currently involves the HS operator passing credentials to the clients, not the other way around. This is good for UX since it means that all configuration is performed by the HS operator (who can be assumed technical), instead of its clients (who should be assumed to be non-technical). All clients need to do is copy-paste the auth line to their torrc. I feel like this UX should be maintained, except if there is a very strong reason to break it.
I think your proposal could be slightly tweaked to fit the above UX, if the HS generates the client's private keys, and then passes them to the clients. The rest works the same. Perhaps we can also give the option for clients to generate the keys themselves if they so want.
Having the HS generate its client's private keys, kind of beats the purpose of having assymetric crypto keys, since we basically treat them as shared secrets. However, I don't think this changes the threat model in any significant way, as the hidden service can be seen a trusted party in some sense. Some more thinking needs to be done here.
The way I see it, by using this proposed scheme, we get a nicer cryptographic scheme (symmetric keys kind of suck) and a more compact auth-client format, for the price of a bit more engineering (generating ephemeral keypairs and encoding them in descriptors). I think this might be worth it.