Usage Guide

Morgan <morgan@torproject.org>


NOTE: A high-level understanding of the Gosling protocol and participants is presumed. If you are new, you will most likely want to read the Design Document first.

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 21191.

Overview

This is a guide for using the gosling Rust crate. Additional information about consuming Gosling through the libcgosling C-FFI can be found in the libcgosling section. The toy applications in the /source/examples directory provide bare-bones examples for how to interact with both of these libraries.

The primary types in the gosling crate are the Context and the ContextEvent.

A Context encapsulates everything about a peer in a Gosling-based peer-to-peer network. It manages the Tor Network connectivity, Gosling handshakes, and other implementation details.

Forward progress is handled via the Context::update() method. This method returns a list of ContextEvent objects to be handled by the application. If Context::update() is not called, then the internal state-machine will not progress.

The ContextEvent objects may be purely informative (e.g. tor logs), or may signal some action needed by the application (e.g. to progress a Gosling handshake).

The general life-cycle of a Context object is its initial creation, a request for bootstrap, and repeated calls to Context::update(). During this update cycle, the identity server or endpoint servers can be started and stopped, and connections to peers can be made.

Connecting to the Tor Network

A Context uses a TorProvder object to handle Tor Network connectivity. Currently, only a wrapper around the ‘little-t’ tor daemon is fully supported via the LegacyTorClient type.

Arti support is under development.

Legacy Tor Client

The LegacyTorClient has two modes of operation, which can be configured using a LegacyTorClientConfig enum. To construct a Gosling context, a TorProvider impl

Bundled Tor

A ‘bundled’ tor is a new instance of the tor daemon which is wholly owned and configured by its parent process (the Gosling-using application in this instance). As such, there are various configuration options available.

This is the typical way tor-using applications (e.g. Tor Browser, Ricochet-Refresh, cwtch, OnionShare, etc) access the tor network. These applications also build and package their own tor daemon executable, but that is beyond the scope of Gosling.

System Tor

A ‘system’ tor is a global instance which is used and shared by multiple applications, or even the entire system (e.g. in the Tails operating system).

Identity+Endpoint Server and Client Usage

For a detailed description of the underlying Gosling protocol and stages of the identity and endpoint handshakes, please see the Gosling Protocol specification

Hosting an identity server

All of the identity server functions have the form Context::identity_server_*.

A Gosling peer’s identity server can be started and stopped using the Context::identity_server_start() and Context::identity_server_stop() methods.

Once an identity server is running and published, the Gosling consumer will receive a ContextEvent::IdentityServerPublished event. After this event is received, it is possible for remote peers to connect and begin the identity handshake to request endpoint credentials.

The general flow of an identity server handshake follows:

It should also be noted that at any point in the handshake the server may receive a ContextEvent::IdentityServerHandshakeFailed containing reason for failure.

Requesting an endpoint from an identity server

All of the identity client functions have the form Context::identity_client_*.

A Gosling peer can initiate an endpoint request with the Context::identity_client_begin_handshake() method.

The general flow of an identity client handshake follows:

It should also be noted that at any point in the handshake the client may receive a ContextEvent::IdentityClientHandshakeFailed containing reason for failure.

At any point an identity client handshake can be aborted using the Context::identity_client_abort_handshake() method.

Hosting an endpoint server

All of the endpoint server functions have the form Context::endpoint_server_*.

A Gosling peer’s endpoint server can be started and stopped using the Context::endpoint_server_start() and Context::endpoint_server_stop() methods.

The general of an endpoint server handshake follows:

It should also be noted that at any point in the handshake the server may receive a ContextEvent::EndpointServerHandshakeFailed containing reason for failure.

Requesting a channel from an endpoint server

All of the endpoint client functions have the form Context::endpoint_client_*.

A Gosling peer can initiate a channel request with the Context::endpoint_client_begin_handshake() method.

The general flow of an endpoint client handshake follows:

It should also be noted that at any point in the handshake the client may receive a ContextEvent::EndpointClientHandshakeFailed containing reason for failure.

At any point an endpoint client handshake can be aborted using the Context::endpoint_client_abort_handshake() method.

Cryptographic Types

The Gosling protocol and crate builds upon Tor and its various cryptographic types. These types are outlined and their purposes within Gosling are described here. The implementation for these types lives in the tor-interface crate.

Consumers of Gosling will need to handle safely using and storing these keys.

ed25519 private key

This type of cryptographic key is required to publish an onion-service.

In the Gosling protocol, a peer’s long-term identity is derived from a securely-generated, secret ed25519 private key. This key is used to publish a peer’s identity server and as part of identity client authentication process.

A peer will also have an ed25519 private key for each of the remote peers which have successfully requested endpoint server credentials from it. These keys are used to publish endpoint servers for these peers to connect to.

Gosling also uses this type of key internally in the protocol to sign messages to prove ownership of this key, but consumers of the gosling crate do not need to worry about this.

Consumers of Gosling will use this type when starting identity or endpoint servers. They will also need to securely create an ed25519 private key when creating an intial identity for a peer using the Ed25519PrivateKey::generate() method.

The associated tor-interface type is the Ed25519PrivateKey.

⚠ Warning ⚠

An ed25519 private key MUST never be shared or distributed. It is strongly RECOMMENDED that this type of key be encrypted when stored on disk.

If an adversary were to acquire another Gosling peer’s ed25519 private key, then they would be able to impersonate that peer.

ed25519 public key

This type of cryptographic key is the public-key counterpart to the ed25119 private key. This type is used internally in the Gosling handshakes for verifying cryptographic proofs signed with a counter-parts ed25519 private key.

Consumers of Gosling will not use this type.

The associated tor-interface type is the Ed25519PublicKey.

v3 onion-service service-id

This type is fundamentally an alternate (and equivalent) representation of an ed25519 public key.

A v3 onion-service service-id is in some ways similar to a domain name, as it is the primary type needed by a Tor client to connect to a v3 onion-service.

In Gosling there are two types of v3 onion-service service-ids:

As described in the design document, a peer has a single identity server. This server’s v3 onion-service service-id serves as a peer’s long-term identity.

A peer also has (potentially) many associated endpoint server service-ids, one for each of the remote peers which it has requested endpoint credentials for. The endpoint server service-id is one of the credentials required to connect to an authorised endpoint server.

Consumers of Gosling will encounter this type when attempting to connect to an identity server or endpoint server, and after successfully completing an endpoint request.

The associated tor-interface type is the V3OnionServiceId.

⚠ Warning ⚠

An identity server’s v3 onion-service service-id has to be shared in-order for the peer to complete endpoint requests.

Any adversary which knows a peer’s identity server v3 onion-service id will be able to secretly collect the online/offline status metadata about that identity server. However, it should be noted that the identity server does not need to be online to connect to authorised peers, as they connect through secret endpoint servers.

An endpoint server’s v3 onion-service service-id MUST NOT be shared.

If an adversary were to learn an endpoint server’s v3 onion-service service-id, then they would also be able to secretly collect the online/offline status metadata about that endpoint server.

x25519 private key

This type is used by Gosling as part of v3 onion-service client authorisation. In Gosling, endpoint server’s v3 onion-service descriptors are encrypted using an x25519 public key, such that only the associated x25519 private key holder can read them. The x25519 private key holder is therefore the only party which can connect to their associated endpoint server.

Consumers of Gosling will encounter this type after successfully completing an endpoint request. It will need to be saved and used whenever the peer connects to the associated endpoint server.

Consumers of Gosling do not need to worry about creating x25519 private keys, as the Gosling Context takes care of that.

The associated tor-interface type is the X25519PrivateKey.

⚠ Warning ⚠

An x25519 private key MUST never be shared or distributed. It is strongly RECOMMENDED that this type of key be encrypted when stored on disk. It is also strongly RECOMMENDED that x25519 key-pairs not be re-used across unrelated v3 onion-services.

If an adversary were to acquire the x25519 private key used to encrypt the onion-service descriptors for a particular onion-service, then they would be able connect to that onion-service (presuming the adversary also had the associated onion-service service-id).

If a peer were to re-use an x25519 key-pair for client authorisation, then the multiple identities re-using said key-pair would be linked or associated if an adversary were to discover the key re-use.

x25519 public key

This type of cryptographic key is the public-key counterpart to the x25119 private key. This type is used by Gosling as part of v3 onion-service client authorisation. In Gosling, an endpoint server needs the endpoint client’s x25519 public key to encrypt the v3 onion-service descriptors. This x25519 public key is sent by the identity client when requesting an endpoint server.

Consumers of Gosling will encounter this type after successfully completing an endpoint request. It will need to be saved and used whenever the peer starts the associated endpoint server.

The associated tor-interface type is the X25519PublicKey.

⚠ Warning ⚠

It is strongly RECOMMENDED that x25519 key-pairs not be re-used across unrelated v3 onion-services.

If a peer were to re-use an x25519 key-pair for client authorisation, then the multiple identities re-using said key-pair would be linked or associated if an adversary were to discover the key re-use.

libcgosling

The libcgosling library wraps the gosling crate in a C-FFI. It can be built as either a static or shared library. All non-Rust (e.g. C/C++, Java, Python, etc) bindings to the gosling crate ultimately goes through libcgosling.

Most of the various (required) Rust types used in the gosling and tor-interface crates have equivalent C types. In general, a Rust type Foo maps to a C struct gosling_foo_t.

One major exception to this is the ContextEvent type. Rather than directly exposing Context::update() and returning a list of gosling_context_event_ts, libcgosling instead depends on a callback mechanism inspired by the GLFW library. The libcgosling consumer must register callbacks to handle events which are called during the execution of the gosling_context_poll_events() function.