diff options
Diffstat (limited to 'spec/rend-spec/introduction-protocol.md')
-rw-r--r-- | spec/rend-spec/introduction-protocol.md | 755 |
1 files changed, 755 insertions, 0 deletions
diff --git a/spec/rend-spec/introduction-protocol.md b/spec/rend-spec/introduction-protocol.md new file mode 100644 index 0000000..0181dd2 --- /dev/null +++ b/spec/rend-spec/introduction-protocol.md @@ -0,0 +1,755 @@ +<a id="rend-spec-v3.txt-3"></a> + +# The introduction protocol {#INTRO-PROTOCOL} + +The introduction protocol proceeds in three steps. + +First, a hidden service host builds an anonymous circuit to a Tor +node and registers that circuit as an introduction point. + +Single Onion Services attempt to build a non-anonymous single-hop circuit, +but use an anonymous 3-hop circuit if: + +```text + * the intro point is on an address that is configured as unreachable via + a direct connection, or + * the initial attempt to connect to the intro point over a single-hop + circuit fails, and they are retrying the intro point connection. + + [After 'First' and before 'Second', the hidden service publishes its + introduction points and associated keys, and the client fetches + them as described in section [HSDIR] above.] +``` + +Second, a client builds an anonymous circuit to the introduction +point, and sends an introduction request. + +Third, the introduction point relays the introduction request along +the introduction circuit to the hidden service host, and acknowledges +the introduction request to the client. + +<a id="rend-spec-v3.txt-3.1"></a> + +## Registering an introduction point {#REG_INTRO_POINT} + +<a id="rend-spec-v3.txt-3.1.1"></a> + +### Extensible ESTABLISH_INTRO protocol {#EST_INTRO} + +When a hidden service is establishing a new introduction point, it +sends an ESTABLISH_INTRO message with the following contents: + +```text + AUTH_KEY_TYPE [1 byte] + AUTH_KEY_LEN [2 bytes] + AUTH_KEY [AUTH_KEY_LEN bytes] + N_EXTENSIONS [1 byte] + N_EXTENSIONS times: + EXT_FIELD_TYPE [1 byte] + EXT_FIELD_LEN [1 byte] + EXT_FIELD [EXT_FIELD_LEN bytes] + HANDSHAKE_AUTH [MAC_LEN bytes] + SIG_LEN [2 bytes] + SIG [SIG_LEN bytes] +``` + +The AUTH_KEY_TYPE field indicates the type of the introduction point +authentication key and the type of the MAC to use in +HANDSHAKE_AUTH. Recognized types are: + +```text + [00, 01] -- Reserved for legacy introduction messages; see + [LEGACY_EST_INTRO below] + [02] -- Ed25519; SHA3-256. +``` + +The AUTH_KEY_LEN field determines the length of the AUTH_KEY +field. The AUTH_KEY field contains the public introduction point +authentication key, KP_hs_ipt_sid. + +The EXT_FIELD_TYPE, EXT_FIELD_LEN, EXT_FIELD entries are reserved for +extensions to the introduction protocol. Extensions with +unrecognized EXT_FIELD_TYPE values must be ignored. +(`EXT_FIELD_LEN` may be zero, in which case EXT_FIELD is absent.) + +```text + Unless otherwise specified in the documentation for an extension type: + * Each extension type SHOULD be sent only once in a message. + * Parties MUST ignore any occurrences all occurrences of an extension + with a given type after the first such occurrence. + * Extensions SHOULD be sent in numerically ascending order by type. + (The above extension sorting and multiplicity rules are only defaults; + they may be overridden in the descriptions of individual extensions.) +``` + +The following extensions are currently defined: + +| `EXT_FIELD_TYPE` | Name | +| ---------------- | -------------- | +| `[01]` | [`DOS_PARAMS`] | + +[`DOS_PARAMS`]: #DOS_PARAMS + +The HANDSHAKE_AUTH field contains the MAC of all earlier fields in +the message using as its key the shared per-circuit material ("KH") +generated during the circuit extension protocol; see tor-spec.txt +section 5.2, "Setting circuit keys". It prevents replays of +ESTABLISH_INTRO messages. + +SIG_LEN is the length of the signature. + +SIG is a signature, using AUTH_KEY, of all contents of the message, up +to but not including SIG_LEN and SIG. These contents are prefixed +with the string "Tor establish-intro cell v1". + +> (Note that this string is _sic_; +> it predates our efforts to distinguish cells from relay messages.) + +Upon receiving an ESTABLISH_INTRO message, a Tor node first decodes the +key and the signature, and checks the signature. The node must reject +the ESTABLISH_INTRO message and destroy the circuit in these cases: + +```text + * If the key type is unrecognized + * If the key is ill-formatted + * If the signature is incorrect + * If the HANDSHAKE_AUTH value is incorrect + + * If the circuit is already a rendezvous circuit. + * If the circuit is already an introduction circuit. + [TODO: some scalability designs fail there.] + * If the key is already in use by another circuit. +``` + +Otherwise, the node must associate the key with the circuit, for use +later in INTRODUCE1 messages. + + + +<a id="rend-spec-v3.txt-3.1.1.1"></a> + +#### Denial-of-Service defense extension (DOS\_PARAMS) {#EST_INTRO_DOS_EXT} + +<a id="DOS_PARAMS"></a> +The `DOS_PARAMS` extension +in ESTABLISH_INTRO +is used to send Denial-of-Service (DoS) parameters to +the introduction point in order for it to apply them for the introduction +circuit. + +This is for the [rate limiting DoS mitigation](../dos-spec/overview.md#hs-intro-rate) specifically. + +The `EXT_FIELD_TYPE` value for the `DOS_PARAMS` extension is `[01]`. + +The content is defined as follows: + +| Field | Size | Description | +| ----------------- | ---- | -------------------- | +| `N_PARAMS` | 1 | Number of parameters | +| `N_PARAMS` times: | | | +| - PARAM_TYPE | 1 | Identifier for a parameter | +| - PARAM_VALUE | 8 | Integer value | + +Recognized values for `PARAM_TYPE` in this extension are: + +| `PARAM_TYPE` | Name | Min | Max | +| ----------- | -------------------------------- | --- | ---------- | +| `[01]` | [`DOS_INTRODUCE2_RATE_PER_SEC`] | 0 | 0x7fffffff | +| `[02]` | [`DOS_INTRODUCE2_BURST_PER_SEC`] | 0 | 0x7fffffff | + +[`DOS_INTRODUCE2_RATE_PER_SEC`]: #DOS_INTRODUCE2_RATE_PER_SEC +[`DOS_INTRODUCE2_BURST_PER_SEC`]: #DOS_INTRODUCE2_BURST_PER_SEC + +Together, these parameters configure a token bucket +that determines how many INTRODUCE2 messages +the introduction point may send to the service. + +<span id="DOS_INTRODUCE2_RATE_PER_SEC"> +The `DOS_INTRODUCE2_RATE_PER_SEC` parameter defines the maximum +average rate of messages; +</span> +<span id="DOS_INTRODUCE2_BURST_PER_SEC"> +The `DOS_INTRODUCE2_BURST_PER_SEC` parameter defines the largest +allowable burst of messages +(that is, the size of the token bucket). +</span> + +> Technically speaking, the `BURST` parameter is misnamed +> in that it is not actually "per second": +> only a _rate_ has an associated time. + +If either of these parameters is set to 0, +the defense is disabled, +and the introduction point should ignore the other parameter. + +If the burst is lower than the rate, +the introduction point SHOULD ignore the extension. + +> Using this extension extends the body of the ESTABLISH_INTRO message by 19 +> bytes bringing it from 134 bytes to 155 bytes. + +When this extension is not _sent_, +introduction points use default settings +taken from taken from the consensus parameters +[HiddenServiceEnableIntroDoSDefense](../param-spec.md#HiddenServiceEnableIntroDoSDefense), +[HiddenServiceEnableIntroDoSRatePerSec](../param-spec.md#HiddenServiceEnableIntroDoSRatePerSec), +and +[HiddenServiceEnableIntroDoSBurstPerSec](../param-spec.md#HiddenServiceEnableIntroDoSBurstPerSec). + +This extension can only be used with relays supporting the protocol version +["HSIntro=5"](../tor-spec/subprotocol-versioning.md#HSIntro). + +Introduced in tor-0.4.2.1-alpha. + +<a id="rend-spec-v3.txt-3.1.2"></a> + +## Registering an introduction point on a legacy Tor node {#LEGACY_EST_INTRO} + +> This section is obsolete and refers to a workaround for now-obsolete Tor +> relay versions. It is included for historical reasons. + +Tor nodes should also support an older version of the ESTABLISH_INTRO +message, first documented in rend-spec.txt. New hidden service hosts +must use this format when establishing introduction points at older +Tor nodes that do not support the format above in \[EST_INTRO\]. + +In this older protocol, an ESTABLISH_INTRO message contains: + +```text + KEY_LEN [2 bytes] + KEY [KEY_LEN bytes] + HANDSHAKE_AUTH [20 bytes] + SIG [variable, up to end of relay message body] + + The KEY_LEN variable determines the length of the KEY field. +``` + +The KEY field is the ASN1-encoded legacy RSA public key that was also +included in the hidden service descriptor. + +The HANDSHAKE_AUTH field contains the SHA1 digest of (KH | "INTRODUCE"). + +The SIG field contains an RSA signature, using PKCS1 padding, of all +earlier fields. + +Older versions of Tor always use a 1024-bit RSA key for these introduction +authentication keys. + +<a id="rend-spec-v3.txt-3.1.3"></a> + +### Acknowledging establishment of introduction point {#INTRO_ESTABLISHED} + +After setting up an introduction circuit, the introduction point reports its +status back to the hidden service host with an INTRO_ESTABLISHED message. + +The INTRO_ESTABLISHED message has the following contents: + +```text + N_EXTENSIONS [1 byte] + N_EXTENSIONS times: + EXT_FIELD_TYPE [1 byte] + EXT_FIELD_LEN [1 byte] + EXT_FIELD [EXT_FIELD_LEN bytes] +``` + +Older versions of Tor send back an empty INTRO_ESTABLISHED message instead. +Services must accept an empty INTRO_ESTABLISHED message from a legacy relay. +\[The above paragraph is obsolete and refers to a workaround for +now-obsolete Tor relay versions. It is included for historical reasons.\] + +The same rules for multiplicity, ordering, and handling unknown types +apply to the extension fields here as described \[EST_INTRO\] above. + +<a id="rend-spec-v3.txt-3.2"></a> + +## Sending an INTRODUCE1 message to the introduction point {#SEND_INTRO1} + +In order to participate in the introduction protocol, a client must +know the following: + +```text + * An introduction point for a service. + * The introduction authentication key for that introduction point. + * The introduction encryption key for that introduction point. +``` + +The client sends an INTRODUCE1 message to the introduction point, +containing an identifier for the service, an identifier for the +encryption key that the client intends to use, and an opaque blob to +be relayed to the hidden service host. + +In reply, the introduction point sends an INTRODUCE_ACK message back to +the client, either informing it that its request has been delivered, +or that its request will not succeed. + +If the INTRODUCE_ACK message indicates success, +the client SHOULD close the circuit to the introduction point, +and not use it for anything else. +If the INTRODUCE_ACK message indicates failure, +the client MAY try a different introduction point. +It MAY reach the different introduction point +either by extending its introduction circuit an additional hop, +or by building a new introduction circuit. + +```text + [TODO: specify what tor should do when receiving a malformed message. Drop it? + Kill circuit? This goes for all possible messages.] +``` + +<a id="rend-spec-v3.txt-3.2.1"></a> + +### Extensible INTRODUCE1 message format {#FMT_INTRO1} + +When a client is connecting to an introduction point, INTRODUCE1 messages +should be of the form: + +```text + LEGACY_KEY_ID [20 bytes] + AUTH_KEY_TYPE [1 byte] + AUTH_KEY_LEN [2 bytes] + AUTH_KEY [AUTH_KEY_LEN bytes] + N_EXTENSIONS [1 byte] + N_EXTENSIONS times: + EXT_FIELD_TYPE [1 byte] + EXT_FIELD_LEN [1 byte] + EXT_FIELD [EXT_FIELD_LEN bytes] + ENCRYPTED [Up to end of relay message body] +``` + +The `ENCRYPTED` field is described in the \[PROCESS_INTRO2\] section. + +AUTH_KEY_TYPE is defined as in \[EST_INTRO\]. Currently, the only value of +AUTH_KEY_TYPE for this message is an Ed25519 public key \[02\]. + +The LEGACY_KEY_ID field is used to distinguish between legacy and new style +INTRODUCE1 messages. In new style INTRODUCE1 messages, LEGACY_KEY_ID is 20 zero +bytes. Upon receiving an INTRODUCE1 messages, the introduction point checks the +LEGACY_KEY_ID field. If LEGACY_KEY_ID is non-zero, the INTRODUCE1 message +should be handled as a legacy INTRODUCE1 message by the intro point. + +Upon receiving a INTRODUCE1 message, the introduction point checks +whether AUTH_KEY matches the introduction point authentication key for an +active introduction circuit. If so, the introduction point sends an +INTRODUCE2 message with exactly the same contents to the service, and sends an +INTRODUCE_ACK response to the client. + +(Note that the introduction point does not "clean up" the +INTRODUCE1 message that it retransmits. Specifically, it does not +change the order or multiplicity of the extensions sent by the +client.) + +The same rules for multiplicity, ordering, and handling unknown types +apply to the extension fields here as described \[EST_INTRO\] above. + +<a id="rend-spec-v3.txt-3.2.2"></a> + +### INTRODUCE_ACK message format. {#INTRO_ACK} + +An INTRODUCE_ACK message has the following fields: + +```text + STATUS [2 bytes] + N_EXTENSIONS [1 bytes] + N_EXTENSIONS times: + EXT_FIELD_TYPE [1 byte] + EXT_FIELD_LEN [1 byte] + EXT_FIELD [EXT_FIELD_LEN bytes] + + Recognized status values are: + + [00 00] -- Success: message relayed to hidden service host. + [00 01] -- Failure: service ID not recognized + [00 02] -- Bad message format + [00 03] -- Can't relay message to service +``` + +The same rules for multiplicity, ordering, and handling unknown types +apply to the extension fields here as described \[EST_INTRO\] above. + +<a id="rend-spec-v3.txt-3.3"></a> + +## Processing an INTRODUCE2 message at the hidden service. {#PROCESS_INTRO2} + +Upon receiving an INTRODUCE2 message, the hidden service host checks whether +the AUTH_KEY or LEGACY_KEY_ID field matches the keys for this +introduction circuit. + +The service host then checks whether it has received a message with these +contents or rendezvous cookie before. If it has, it silently drops it as a +replay. (It must maintain a replay cache for as long as it accepts messages +with the same encryption key. Note that the encryption format below should +be non-malleable.) + +If the message is not a replay, it decrypts the ENCRYPTED field, +establishes a shared key with the client, and authenticates the whole +contents of the message as having been unmodified since they left the +client. There may be multiple ways of decrypting the ENCRYPTED field, +depending on the chosen type of the encryption key. Requirements for +an introduction handshake protocol are described in +\[INTRO-HANDSHAKE-REQS\]. We specify one below in section +\[NTOR-WITH-EXTRA-DATA\]. + +The decrypted plaintext must have the form: + +```text + RENDEZVOUS_COOKIE [20 bytes] + N_EXTENSIONS [1 byte] + N_EXTENSIONS times: + EXT_FIELD_TYPE [1 byte] + EXT_FIELD_LEN [1 byte] + EXT_FIELD [EXT_FIELD_LEN bytes] + ONION_KEY_TYPE [1 bytes] + ONION_KEY_LEN [2 bytes] + ONION_KEY [ONION_KEY_LEN bytes] + NSPEC (Number of link specifiers) [1 byte] + NSPEC times: + LSTYPE (Link specifier type) [1 byte] + LSLEN (Link specifier length) [1 byte] + LSPEC (Link specifier) [LSLEN bytes] + PAD (optional padding) [up to end of plaintext] +``` + +Upon processing this plaintext, the hidden service makes sure that +any required authentication is present in the extension fields, and +then extends a rendezvous circuit to the node described in the LSPEC +fields, using the ONION_KEY to complete the extension. As mentioned +in \[BUILDING-BLOCKS\], the "TLS-over-TCP, IPv4" and "Legacy node +identity" specifiers must be present. + +As of 0.4.1.1-alpha, clients include both IPv4 and IPv6 link specifiers +in INTRODUCE1 messages. All available addresses SHOULD be included in the +message, regardless of the address that the client actually used to extend +to the rendezvous point. + +The hidden service should handle invalid or unrecognised link specifiers +the same way as clients do in section 2.5.2.2. In particular, services +SHOULD perform basic validity checks on link specifiers, and SHOULD NOT +reject unrecognised link specifiers, to avoid information leaks. +The list of link specifiers received here SHOULD either be rejected, or +sent verbatim when extending to the rendezvous point, in the same order +received. + +The service MAY reject the list of link specifiers if it is +inconsistent with relay information from the directory, but SHOULD +NOT modify it. + +The ONION_KEY_TYPE field is: + +\[01\] NTOR: ONION_KEY is 32 bytes long. + +The ONION_KEY field describes the onion key that must be used when +extending to the rendezvous point. It must be of a type listed as +supported in the hidden service descriptor. + +The PAD field should be filled with zeros; its size should be chosen +so that the INTRODUCE2 message occupies a fixed maximum size, in +order to hide the length of the encrypted data. (This maximum size is +490, since we assume that a future Tor implementations will implement +proposal 340 and thus lower the number of bytes that can be contained +in a single relay message.) Note also that current versions of Tor +only pad the INTRODUCE2 message up to 246 bytes. + +Upon receiving a well-formed INTRODUCE2 message, the hidden service host +will have: + +```text + * The information needed to connect to the client's chosen + rendezvous point. + * The second half of a handshake to authenticate and establish a + shared key with the hidden service client. + * A set of shared keys to use for end-to-end encryption. +``` + +The same rules for multiplicity, ordering, and handling unknown types +apply to the extension fields here as described \[EST_INTRO\] above. + +### INTRODUCE1/INTRODUCE2 Extensions + +The following sections details the currently supported or reserved extensions +of an `INTRODUCE1`/`INTRODUCE2` message. + +Note that there are two sets of extensions in `INTRODUCE1`/`INTRODUCE2`: +one in the top-level, unencrypted portion, +and one within the plaintext of ENCRYPTED +(ie, after RENDEZVOUS_COOKIE and before ONION_KEY_TYPE. + +The sets of extensions allowed in each part of the message are disjoint: +each extension is valid in only *one* of the two places. + +Nevertheless, for historical reasons, +both kinds of extension are listed in this section, +and they use nonoverlapping values of `EXT_FIELD_TYPE`. + +#### Congestion Control + +This is used to request that the rendezvous circuit with the service be +configured with congestion control. + + EXT_FIELD_TYPE: + + \[01\] -- Congestion Control Request. + +This field is has zero body length. Its presence signifies that the client +wants to use congestion control. The client MUST NOT set this field, or use +ntorv3, if the service did not list "2" in the `FlowCtrl` line in the +descriptor. The client SHOULD NOT provide this field if the consensus parameter +'cc_alg' is 0. + +This appears in the ENCRYPTED section of the INTRODUCE1/INTRODUCE2 message. + +#### Proof-of-Work (PoW) {#INTRO1_POW_EXT} + +This extension can be used to optionally attach a proof of work to the introduction request. +The proof must be calculated using unique parameters appropriate for this specific service. +An acceptable proof will raise the priority of this introduction request according to the proof's verified computational effort. + +This is for the [proof-of-work DoS mitigation](../dos-spec/overview.md#hs-intro-pow), described in depth by the [Proof of Work for onion service introduction](../hspow-spec/index.md) specification. + +This appears in the ENCRYPTED section of the INTRODUCE1/INTRODUCE2 message. + +The content is defined as follows: + +EXT_FIELD_TYPE: + +\[02\] -- `PROOF_OF_WORK` + +```text +The EXT_FIELD content format is: + + POW_SCHEME [1 byte] + POW_NONCE [16 bytes] + POW_EFFORT [4 bytes] + POW_SEED [4 bytes] + POW_SOLUTION [16 bytes] + +where: + +POW_SCHEME is 1 for the `v1` protocol specified here +POW_NONCE is the nonce value chosen by the client's solver +POW_EFFORT is the effort value chosen by the client, + as a 32-bit integer in network byte order +POW_SEED identifies which seed was in use, by its first 4 bytes +POW_SOLUTION is a matching proof computed by the client's solver +``` + +Only SCHEME 1, `v1`, is currently defined. +Other schemes may have a different format, +after the POW_SCHEME byte. +A correctly functioning client only submits solutions with a scheme and seed which were advertised by the server +(using a "pow-params" Item in the +[HS descriptor](hsdesc-encrypt.md#second-layer-plaintext)) +and have not yet expired. +An extension with an unknown scheme or expired seed is suspicious and SHOULD result in introduction failure. + +Introduced in tor-0.4.8.1-alpha. + +#### Subprotocol Request + +\[RESERVED\] + + EXT_FIELD_TYPE: + + \[03\] -- Subprotocol Request + +<a id="rend-spec-v3.txt-3.3.1"></a> + +### Introduction handshake encryption requirements {#INTRO-HANDSHAKE-REQS} + +When decoding the encrypted information in an INTRODUCE2 message, a +hidden service host must be able to: + +```text + * Decrypt additional information included in the INTRODUCE2 message, + to include the rendezvous token and the information needed to + extend to the rendezvous point. + + * Establish a set of shared keys for use with the client. + + * Authenticate that the message has not been modified since the client + generated it. +``` + +Note that the old TAP-derived protocol of the previous hidden service +design achieved the first two requirements, but not the third. + +```text +3.3.2. Example encryption handshake: ntor with extra data + [NTOR-WITH-EXTRA-DATA] + + [TODO: relocate this] +``` + +This is a variant of the ntor handshake (see tor-spec.txt, section +5.1.4; see proposal 216; and see "Anonymity and one-way +authentication in key-exchange protocols" by Goldberg, Stebila, and +Ustaoglu). + +It behaves the same as the ntor handshake, except that, in addition +to negotiating forward secure keys, it also provides a means for +encrypting non-forward-secure data to the server (in this case, to +the hidden service host) as part of the handshake. + +Notation here is as in section 5.1.4 of tor-spec.txt, which defines +the ntor handshake. + +The PROTOID for this variant is "tor-hs-ntor-curve25519-sha3-256-1". +We also use the following tweak values: + +```text + t_hsenc = PROTOID | ":hs_key_extract" + t_hsverify = PROTOID | ":hs_verify" + t_hsmac = PROTOID | ":hs_mac" + m_hsexpand = PROTOID | ":hs_key_expand" +``` + +To make an INTRODUCE1 message, the client must know a public encryption +key B for the hidden service on this introduction circuit. The client +generates a single-use keypair: + +x,X = KEYGEN() + +and computes: + +```text + intro_secret_hs_input = EXP(B,x) | AUTH_KEY | X | B | PROTOID + info = m_hsexpand | N_hs_subcred + hs_keys = KDF(intro_secret_hs_input | t_hsenc | info, S_KEY_LEN+MAC_LEN) + ENC_KEY = hs_keys[0:S_KEY_LEN] + MAC_KEY = hs_keys[S_KEY_LEN:S_KEY_LEN+MAC_KEY_LEN] + + and sends, as the ENCRYPTED part of the INTRODUCE1 message: + + CLIENT_PK [PK_PUBKEY_LEN bytes] + ENCRYPTED_DATA [Padded to length of plaintext] + MAC [MAC_LEN bytes] +``` + +Substituting those fields into the INTRODUCE1 message body format +described in \[FMT_INTRO1\] above, we have + +```text + LEGACY_KEY_ID [20 bytes] + AUTH_KEY_TYPE [1 byte] + AUTH_KEY_LEN [2 bytes] + AUTH_KEY [AUTH_KEY_LEN bytes] + N_EXTENSIONS [1 bytes] + N_EXTENSIONS times: + EXT_FIELD_TYPE [1 byte] + EXT_FIELD_LEN [1 byte] + EXT_FIELD [EXT_FIELD_LEN bytes] + ENCRYPTED: + CLIENT_PK [PK_PUBKEY_LEN bytes] + ENCRYPTED_DATA [Padded to length of plaintext] + MAC [MAC_LEN bytes] +``` + +(This format is as documented in \[FMT_INTRO1\] above, except that here +we describe how to build the ENCRYPTED portion.) + +Here, the encryption key plays the role of B in the regular ntor +handshake, and the AUTH_KEY field plays the role of the node ID. +The CLIENT_PK field is the public key X. The ENCRYPTED_DATA field is +the message plaintext, encrypted with the symmetric key ENC_KEY. The +MAC field is a MAC of all of the message from the AUTH_KEY through the +end of ENCRYPTED_DATA, using the MAC_KEY value as its key. + +To process this format, the hidden service checks PK_VALID(CLIENT_PK) +as necessary, and then computes ENC_KEY and MAC_KEY as the client did +above, except using EXP(CLIENT_PK,b) in the calculation of +intro_secret_hs_input. The service host then checks whether the MAC is +correct. If it is invalid, it drops the message. Otherwise, it computes +the plaintext by decrypting ENCRYPTED_DATA. + +The hidden service host now completes the service side of the +extended ntor handshake, as described in tor-spec.txt section 5.1.4, +with the modified PROTOID as given above. To be explicit, the hidden +service host generates a keypair of y,Y = KEYGEN(), and uses its +introduction point encryption key 'b' to compute: + +```text + intro_secret_hs_input = EXP(X,b) | AUTH_KEY | X | B | PROTOID + info = m_hsexpand | N_hs_subcred + hs_keys = KDF(intro_secret_hs_input | t_hsenc | info, S_KEY_LEN+MAC_LEN) + HS_DEC_KEY = hs_keys[0:S_KEY_LEN] + HS_MAC_KEY = hs_keys[S_KEY_LEN:S_KEY_LEN+MAC_KEY_LEN] + + (The above are used to check the MAC and then decrypt the + encrypted data.) + + rend_secret_hs_input = EXP(X,y) | EXP(X,b) | AUTH_KEY | B | X | Y | PROTOID + NTOR_KEY_SEED = MAC(rend_secret_hs_input, t_hsenc) + verify = MAC(rend_secret_hs_input, t_hsverify) + auth_input = verify | AUTH_KEY | B | Y | X | PROTOID | "Server" + AUTH_INPUT_MAC = MAC(auth_input, t_hsmac) + + (The above are used to finish the ntor handshake.) + + The server's handshake reply is: + + SERVER_PK Y [PK_PUBKEY_LEN bytes] + AUTH AUTH_INPUT_MAC [MAC_LEN bytes] +``` + +These fields will be sent to the client in a RENDEZVOUS1 message using the +HANDSHAKE_INFO element (see \[JOIN_REND\]). + +The hidden service host now also knows the keys generated by the +handshake, which it will use to encrypt and authenticate data +end-to-end between the client and the server. These keys are as +computed with the +[ntor handshake](../tor-spec/create-created-cells.html#ntor), +except that instead of using +AES-128 and SHA1 for this hop, we use AES-256 and SHA3-256. + +<a id="rend-spec-v3.txt-3.4"></a> + +## Authentication during the introduction phase. {#INTRO-AUTH} + +Hidden services may restrict access only to authorized users. +One mechanism to do so is the credential mechanism, where only users who +know the credential for a hidden service may connect at all. + +There is one defined authentication type: `ed25519`. + +<a id="rend-spec-v3.txt-3.4.1"></a> + +### Ed25519-based authentication `ed25519` {#ed25519-auth} + +(NOTE: This section is not implemented by Tor. It is likely +that we would want to change its design substantially before +deploying any implementation. At the very least, we would +want to bind these extensions to a single onion service, to +prevent replays. We might also want to look for ways to limit +the number of keys a user needs to have.) + +To authenticate with an Ed25519 private key, the user must include an +extension field in the encrypted part of the INTRODUCE1 message with an +EXT_FIELD_TYPE type of \[02\] and the contents: + +```text + Nonce [16 bytes] + Pubkey [32 bytes] + Signature [64 bytes] +``` + +Nonce is a random value. Pubkey is the public key that will be used +to authenticate. \[TODO: should this be an identifier for the public +key instead?\] Signature is the signature, using Ed25519, of: + +```text + "hidserv-userauth-ed25519" + Nonce (same as above) + Pubkey (same as above) + AUTH_KEY (As in the INTRODUCE1 message) +``` + +The hidden service host checks this by seeing whether it recognizes +and would accept a signature from the provided public key. If it +would, then it checks whether the signature is correct. If it is, +then the correct user has authenticated. + +Replay prevention on the whole message is sufficient to prevent replays +on the authentication. + +Users SHOULD NOT use the same public key with multiple hidden +services. |