Encryption keys & algorithms, directory servers and channels
References:
- https://spec.torproject.org/
- https://spec.torproject.org/tor-spec/negotiating-channels.html
- https://spec.torproject.org/cert-spec.html
Other articles on the topic:
- Introduction and general Tor concepts
- Encryption keys & algorithms, directory servers and channels (this one)
Disclaimer 1:
While I did my best to be as accurate as possible, the topic is complex and I am really good at doing mistakes. If you notice anything wrong, please reach out. Moreover, I skipped some details to keep the content concise; so please, use the references above to deepen your knowledge.
Disclaimer 2:
I could be wrong, but I think that the Tor documentation contains some error in the naming of the keys. In particular, the public and private keys seem swapped in multiple places (you are not supposed to use a public key to generate a signature). Take your time and investigate deeper, if needed.
In the previous article I did my best to provide an introduction to the main concepts of the Tor network. What follows is an overview of the various encryption keys in use, how relays can be contacted and how channels are established.
Generating keys is free. Encryption algorithms are free too. So let’s use plenty of them.
Important note before starting: in the following paragraph, if the name of an asymmetric key starts with "kp"
, I am speaking about a public key, while if the name starts with "ks"
, it is a private key. Moreover, inside the round brackets you can find the name of the keys as defined inside the Tor official documentation.
To function, a Tor relay needs the following key pairs:
- Identity keys;
- Online keys;
- Circuit extension keys (a.k.a. onion keys);
- Link keys.
Identity Keys (kp_relayid_ed
/ ks_relayid_ed
– kp_relayid_rsa
/ ks_relayid_rsa
)
This is an Ed25519 key pair that is used to uniquely identify the relay inside the Tor network. They never expire and are never regenerated. If they change, the identity of the relay changes too. If it happens, the relay becomes brand new for the Tor network.
Having long-lasting, critically important keys poses a problem: if they are compromised, the impact is huge. For this reason, the private identity key is kept offline and used only when strictly necessary.
A 1024 bit RSA key pair is also generated, even if its existence is for legacy purposes. Whenever a signature generated by the identity key must be verified, the following process applies:
- if the signature generated by the RSA key cannot be verified, the process stops;
- if the signature generated by the RSA key can be verified, the process continues and the signature generated by the EC key is also verified;
- for the signature verification to be completed successfully, both signatures must be verified.
Online keys (kp_relaysign_ed
/ ks_relaysign_ed
)
This is also an Ed22519 key pair. It is used to sign all the other keys, or when other key pairs cannot be used. They are signed by ks_relayid_ed
and their sole purpose is to allow the private identity keys to remain offline for most of the time.
This key pair is used to sign:
- the server descriptor sent to the directory servers;
- the other keys pairs.
Circuit extension keys (kp_ktor
/ ks_ktor
– kp_onion_tap
/ ks_onion_tap
)
Each relay has one or more circuit extension keys (also called onion keys), which last on the order of weeks and whose purpose is the creation or the extension of a circuit, to perform a one-way authenticated key exchange.
The *_ktor
key pair is based on Curve25519 and is used for the ntor and ntorv3 circuit extension handshakes, while the *_onion_tap
RSA 1024 key pair is used for the legacy tap circuit extension handshake.
Link keys (kp_link_ed
/ ks_link_ed
)
During the channel negotiation handshake between relays, these short-term keys are used for the link authentication. These keys are signed by the ks_relaysign_ed
key and are regenerated frequently.
Ephemeral keys. Non-ephemeral security.
The asymmetric keys above have two goals: authenticating relays and sharing ephemeral keys securely. This second goal is achieved with a brilliant key exchange protocol called Diffie-Hellman, in our case based on elliptic curves.
This key exchange allows the relays to share ephemeral, symmetric keys that are used for that specific session and that are never used again. Which is cool but… why bothering?
These keys provide two advantages:
- they guarantee the forward secrecy
- if the current session key is compromised by an attacker, no session can be decrypted/recovered other than the current one;
- if the long term keys are compromised, no session can be decrypted recovered without the associated session keys.
- symmetric algorithms do provide better performances.
Certify identities without certification authorities. The directory servers.
On Internet, the Certification Authorities (CA) are the ones in charge of authenticating entities (services, companies, people, etc…) by signing the entity’s certificate with the CA private key. Any other entity receiving this signed certificate can use the CA public key (that is well known and normally embedded in the OS/browser) to verify the entity’s identity.
On Tor, there is no CA. How can be relays authenticated? The process is not that straightforward.
First of all, any relay generates what is called a server descriptor, that is a text document whose content is defined in the directory protocol. Broadly speaking, it contains:
kp_relayid_ed
;kp_relayid_rsa
;kp_relaysign_ed
;kp_ktor
;- the IP address of the relay;
- additional information, like contact points, TCP ports in use, policies, etc…;
- the signature of all the above information.
The list of the server descriptors is downloaded at the first start by the client/relay and is updated when needed. This is all is needed for contacting a relay and establishing a channel.
One important detail: the addresses of the directory servers are fixed and provided together with the Tor application. In theory, a user could change them, but this would completely undermine the client security and it does not make any sense at all (in common usage scenarios).
Establishing channels.
In the following paragraphs, I will use the term “initiator” to indicate both a client a relay initiating a connection. If there is any difference between the two, this will be explicitly explained. The term “responder” indicates the endpoint to which the channel is being established. Those are the terms used by the Tor documentation.
As you may recall from the first article, you can think of a channel as a pipe between a client and a relay or between two relays. A set of channels connecting a client with the exit node or with the destination onion service is called a circuit.
Now, how are those channels established?
From outside, a channel is nothing more than a TLS session. If compared against a normal TLS session, the ones established by Tor have two important differences: there is no CA to be used to validate the exchanged certificates and the communication inside the TLS session is encapsulated in additional layers of encryption.
The first check against the responder’s identity is done by checking if the certificate sent during the establishment of the TLS session is signed with the responder’s ks_relayid_ed
private key.
Once the session has been established, this is used by Tor to exchange multiple cells (the messages exchanged by parties in Tor), leveraged by the link protocol to create a real Tor channel.
The first cell is the CERTS cell sent by the responder. It describes the keys that the Tor instance is claiming to have, and provides certificates to authenticate that those keys belong to it.
The responder’s CERTS cell has two certificates inside. They contain the following keys, respectively:
- the
kp_relaysign_ed
, signed with theks_relayid_ed
; - a TLS certificate, signed with the
ks_relaysign_ed
.
If the two certificates can be verified by the initiator using the certificates it has (the kp_relayid_ed
from the directory servers and the kp_relaysign_ed
from the CERTS cell), the identity of the responder is considered verified.
If the initiator is a relay (e.g.: between the first and the second hop during the creation of a circuit), the responder sends an AUTH_CHALLENGE cell, to which the initiator must respond with a CERTS cell and an AUTHENTICATE cell. The initiator is not authenticated until both the cells are received by the responder.
The initiator’s CERTS cell is identical to the one sent by the responder, but the key inside the signed TLS certificate is deemed to be the public link key, i.e. kp_link_ed
. Of course, it is signed with the
of the initiator.ks_relaysign_ed
From the responder’s AUTH_CHALLENGE cell, the initiator extracts a challenge (a set of randomly generated bytes) and an authentication method, that currently can only be Ed25519-SHA256-RFC5705.
For authenticating itself, the initiator uses the private link key, i.e. ks_link_ed
, to generate a signature over the challenge; it than puts this signature, together with other stuffs (check the official documentation for the details), inside an AUTHENTICATE cell and sends it to the responder. If the responder successfully verifies the content of this second cell, the channel is considered established.
To be honest, one last cell is exchanged, called NETINFO cell, but I will possibly cover it in a future article. It does not use any encryption key, so I skip it for now.