[tor-dev] sketch: An alternative prop224 authentication mechanism based on curve25519

teor teor2345 at gmail.com
Sat Nov 12 19:18:17 UTC 2016

> On 12 Nov. 2016, at 03:41, George Kadianakis <desnacked at riseup.net> wrote:
> teor <teor2345 at gmail.com> writes:
>> [ text/plain ]
>>> On 11 Nov. 2016, at 04:18, George Kadianakis <desnacked at riseup.net> wrote:
>>> George Kadianakis <desnacked at riseup.net> writes:
>>>> [ text/plain ]
>>>> Nick Mathewson <nickm at 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.
>>> OK, I think sooner or later we needed to have a UX discussion about HS
>>> client authorization!
>>> The current rend-spec.txt specifies the torrc options for client auth in
>>> sections 2.3/2.4. We don't do this in prop224 yet, but I think it's
>>> useful because figuring out the torrc format now will help us understand
>>> if the scheme we are making is useful.
>>> Here is a rough proposed UX for prop224 client auth, using Nick's idea
>>> from the top post of this thread. FWIW, I've used the same torrc option
>>> naming as we currently have but we should probably introduce new ones.
>>> -- Hidden Service configuration
>>> A hidden service uses the following torrc line to specify authed clients:
>>>    HiddenServiceAuthorizeClient <auth-type> <client-name>,<client-name>,...
>>> If this option is configured, Tor generates client authorization data
>>> and creates a new "hs_client_auth.txt" file which contains lines with the
>>> following format:
>>>   client-name <client-name> NL
>>>   HidServAuth <onion-address> <desc-x25519-privkey-b64> <intro-ed25519-privkey-b64>  NL
>>> where <client-name> is a nickname for the authed client,
>>> <desc-x25519-key-privb64> is an x25519 private key used to generate
>>> descriptor encryption keys (as Nick specified in top mail), and
>>> <desc-ed25519-privkey-b64> is an ed25519 private key used to perform the
>>> INTRO1 authorization protocol (as specified in section 3.4.2 of prop224).
>>> e.g.
>>>   client-name alice
>>>   HidServAuth a1uik0w1gmfq3i5ievxdm9ceu27e88g6o7pe0rffdw9jmntwkdsd.onion 2vMVLDEAu+rc0rXFONpnor9mfG5xj0ovSh+YWIvOAvQ= qtXjslfyvPokRGFkzGnTXK7ICUNnoFyQRMORN/Zn4ss= 
>>>   client-name bob
>>>   HidServAuth a1uik0w1gmfq3i5ievxdm9ceu27e88g6o7pe0rffdw9jmntwkdsd.onion /ADODiu4Dq6n+Oc5PGkmWmS72OEO9J46DTIWh8Omkck= QlQf+Bsukgjp8iGbdCuCihHHrbp6csN3yDFe8SSaTXU=
>>>   client-name charlie
>>>   HidServAuth a1uik0w1gmfq3i5ievxdm9ceu27e88g6o7pe0rffdw9jmntwkdsd.onion /ADODiu4Dq6n+Oc5PGkmWmS72OEO9J46DTIWh8Omkck= QlQf+Bsukgjp8iGbdCuCihHHrbp6csN3yDFe8SSaTXU=
>>> The idea here is that HS operators find the right HidServAuth line and
>>> paste it to their clients out-of-band, who then copy pastes it into
>>> their torrc file (or ideally plug it through tor browser in the future).
>> I think we should discourage people handing around shared private keys.
>> In particular, it's poor UI for the hidden service to generate private
>> keys that only the user should know.
>> And it's even worse UI for the hidden service to take private keys as
>> input - it should only ever take the public keys as input, even if we
>> decide that it should generate the private keys for clients, it should
>> not need to keep them around.
>>> We should also make it possible for clients to provide their own private
>>> keys. We should introduce a keygen command for clients which generates a
>>> "HidServAuth" line, and then they can pass it to the HS operator, who
>>> puts it in their hs_client_auth.txt. Unclear what's the best UX way to
>>> do this; probably it should be a tor browser utility or sth…
>> I really do think this should be the default. Otherwise, the HS operator
>> knows the private keys. (Although I don't think this breaks much,
>> conceptually, it looks bad.)
> I definitely agree it conceptually looks bad and/or dump for the hidden
> service to generate private keys and pass them to its users, even though
> it probably does not really affect security that much. Let's try to
> think of alternatives:
> a) Clients securely generate keypairs and pass their pubkeys to the HS.
>   This is basically the SSH authorized_keys model, and it looks like
>   the conceptually right way of doing this, but this definitely changes
>   the UX in a major way.
>   I think the most painful thing here is that we will need to introduce
>   a client-side keygen utility that will generate these keypairs, and
>   present them to the user. It's unclear how we would do that, and it's
>   extra engineering and UX analysis, since we need to assume that HS
>   clients are not tech savvy and do not understand what public/private
>   keys are.
>   Also, it means that clients need to _securely_ send credentials to
>   the HS operator

The impact of clients sending the public keys in plain text is that an
adversary who reads them can impersonate the HS to the client (if the
client does not check the HS address). An adversary who modifies
them can deny the client access to the HS (if the HS address is known),
or impersonate the HS to the client (if the HS address is modified at
the same time).

The impact of HSs sending the private keys in plain text is that an
adversary who reads them can impersonate the client to the HS
(unconditionally). An adversary who modifies them can deny the client
access to the HS (if the HS address is known), or impersonate the
client to the HS and the HS to the client - a man-in-the-middle (if
the HS address is modified at the same time).

So from a security perspective, transferring public keys tends to be
safer than transferring private keys. There would have to be a strong
UX counter-argument.

> and then they need to _wait_ till the HS operator
>   adds those creds to Tor, before they are able to visit the HS. Till
>   the HS operator adds their creds to Tor, authed client connections to
>   the HS will fail silently since there is no NACK from the service and
>   they will just be unable to complete rendezvous. We should probably
>   speak with people that use client auth to tell us if this UX will
>   break their model.
> b) We can change the client auth methods to use symmetric keys, instead
>   of assymetric keys. This way we avoid passing private keys to users.

No, the symmetric key *is* the secret key that needs to be protected.
It can be just as sensitive as the private key.

The impact of HSs sending the symmetric keys in plain text is that an
adversary who reads them can impersonate the client to the HS
(unconditionally). An adversary who modifies them can deny the client
access to the HS (if the HS address is known), or impersonate the
client to the HS and the HS to the client - a man-in-the-middle (if
the client does not check the HS address).

>   This might be a plausible way forward and potentially worth exploring. 
>   For descriptor-level authorization, using symmetric keys is
>   straightforward since we just need to do the same thing that we are
>   now doing in rend-spec.txt (it's basically the scheme I posted in
>   https://lists.torproject.org/pipermail/tor-dev/2016-November/011617.html)
>   For intro-level authorization, prop224 suggests we use ed25519
>   signatures for clients to prove ownership of their private key.  We
>   could perhaps switch those signatures to be MAC tags, so that we can
>   perform those with symmetric keys.
> What else can we do here?
> And am I perhaps overthinking of the UX issue here?

Without actual use cases, it will be hard to decide whether the complexity
of an asymmetric scheme is worthwhile.

It certainly is for the user that wants to identify themselves uniquely to
the HS, and ensure they control their credential.

For all other cases, a password or symmetric key is sufficient.

It's worth mentioning that the underlying implementation can use x25519
keys, and we can simply change how they are derived:
* a public key supplied by the client,
* a private key sent by the HS to the client, and transformed into a public
  key by the HS (this provides the same level of security as a symmetric
* a password transformed into a private key by both client and HS using a
  KDF, and transformed into a public key by the HS (this is essentially a
  symmetric key).


Tim Wilson-Brown (teor)

teor2345 at gmail dot com
PGP C855 6CED 5D90 A0C5 29F6 4D43 450C BA7F 968F 094B
xmpp: teor at torproject dot org

More information about the tor-dev mailing list