Hi Nick, you might look at the Noise framework:
http://noiseprotocol.org/noise.html
Noise has a naming scheme for "handshake patterns". Ntor matches what
we call NK1. Your new scheme I think matches NK (the 1 in NK1
indicates a "deferred" pattern where the DH operation that
authenticates the server is performed prior to the 2nd message rather
than the first).
NK1:
<- s
...
-> e
<- e, ee, es
(read as: initiator has pre-knowledge of server's static public key s;
initiator sends their ephemeral in first message; responder sends
their ephemeral in second message, then performs the two 2 DH
operations, hashing them together and using the result for encrypting
future data).
In NK, the ephemeral-static DH is performed earlier so that the first
message's handshake payload can be encrypted:
NK:
<- s
...
-> e, es
<- e, ee
You also wanted to add an (optional) pre-shared key, which Noise supports:
NKpsk0:
<- s
...
-> psk, e, es
<- e, ee
Some advantages of Noise are that you could reuse existing libraries
and Noise's growing body of security analysis.
Also, we're working on KEM extensions for post-quantum, signatures,
and other things, so Noise might make it easier to evolve the protocol
(eg NK1 vs NK vs NKpsk0).
Trevor
On Mon, Jul 12, 2021 at 9:02 AM Nick Mathewson wrote:
>
> ```
> Filename: 332-ntor-v3-with-extra-data.md
> Title: Ntor protocol with extra data, version 3.
> Author: Nick Mathewson
> Created: 12 July 2021
> Status: Open
> ```
>
> # Overview
>
> The ntor handshake is our current protocol for circuit
> establishment.
>
> So far we have two variants of the ntor handshake in use: the "ntor
> v1" that we use for everyday circuit extension (see `tor-spec.txt`)
> and the "hs-ntor" that we use for v3 onion service handshake (see
> `rend-spec-v3.txt`). This document defines a third version of ntor,
> adapting the improvements from hs-ntor for use in regular circuit
> establishment.
>
> These improvements include:
>
> * Support for sending additional encrypted and authenticated
>protocol-setup handshake data as part of the ntor handshake. (The
>information sent from the client to the relay does not receive
>forward secrecy.)
>
> * Support for using an external shared secret that both parties must
>know in order to complete the handshake. (In the HS handshake, this
>is the subcredential. We don't use it for circuit extension, but in
>theory we could.)
>
> * Providing a single specification that can, in the future, be used
>both for circuit extension _and_ HS introduction.
>
> # The improved protocol: an abstract view
>
> Given a client "C" that wants to construct a circuit to a
> relay "S":
>
> The client knows:
> * B: a public "onion key" for S
> * ID: an identity for S, represented as a fixed-length
> byte string.
> * CM: a message that it wants to send to S as part of the
> handshake.
> * An optional "verification" string.
>
> The relay knows:
> * A set of [(b,B)...] "onion key" keypairs. One of them is
> "current", the others are outdated, but still valid.
> * ID: Its own identity.
> * A function for computing a server message SM, based on a given
> client message.
> * An optional "verification" string. This must match the "verification"
> string from the client.
>
> Both parties have a strong source of randomness.
>
> Given this information, the client computes a "client handshake"
> and sends it to the relay.
>
> The relay then uses its information plus the client handshake to see
> if the incoming message is valid; if it is, then it computes a
> "server handshake" to send in reply.
>
> The client processes the server handshake, and either succeeds or fails.
>
> At this point, the client and the relay both have access to:
> * CM (the message the client sent)
> * SM (the message the relay sent)
> * KS (a shared byte stream of arbitrary length, used to compute
> keys to be used elsewhere in the protocol).
>
> Additionally, the client knows that CM was sent _only_ to the relay
> whose public onion key is B, and that KS is shared _only_ with that
> relay.
>
> The relay does not know which client participated in the handshake,
> but it does know that CM came from the same client that generated
> the key X, and that SM and KS were shared _only_ with that client.
>
> Both parties know that CM, SM, and KS were shared correctly, or not
> at all.
>
> Both parties know that they used the same verification string; if
> they did not, they do not learn what the verification string was.
> (This feature is required for HS handshakes.)
>
> # The handshake in detail
>
> ## Notation
>
> We use the following notation:
>
> * `|` -- concatenation
> * `"..."` -- a byte string, with no terminating NUL.
> * `ENCAP(s)` -- an encapsulation function. We define this
> as `htonll(len(s)) | s`. (Note that `len(ENCAP(s)) = len(s) + 8`).
> * `PARTITION(s, n1, n2, n3, ...)` -- a function that partitions a