Tor v3 Hidden Service Descriptor Mechanics: Technical Deep Dive
Tor v3 hidden services use a cryptographically sophisticated system for service discovery that provides significantly stronger security than the deprecated v2 protocol. Understanding how v3 descriptor publishing works helps operators debug hidden service issues, understand the security properties they are depending on, and make informed decisions about service configuration. This guide provides a technical deep dive into the v3 descriptor system: how the .onion address is derived from public keys, how descriptors are published to the distributed hash table maintained by HSDir relays, how clients fetch descriptors without revealing which .onion address they are looking up, and what happens when descriptors expire or HSDirs rotate. This is a reference for operators who want to understand the cryptography behind their .onion service, not just configure it.
Need this done for your project?
We implement, you ship. Async, documented, done in days.
A v3 .onion address is a 56-character base32 encoding of a compound value: the first 32 bytes are the Ed25519 public key of the hidden service, the next 2 bytes are a checksum, and the final byte is the version number (03 for v3). The Ed25519 key pair is generated when you create a hidden service (the hs_ed25519_secret_key and hs_ed25519_public_key files in the hidden service directory). The checksum is calculated as: BLAKE2b_8(b'.onion checksum' || public_key || version). The entire compound is base32-encoded and suffixed with '.onion'. This means the .onion address is a cryptographic commitment to the service's Ed25519 public key - any service presenting a different key cannot claim that .onion address. This is fundamentally stronger than v2, where addresses were derived from RSA-1024 keys that are now considered cryptographically weak.
Descriptor Structure and Content
The hidden service descriptor is a signed document that tells clients how to reach the service (specifically, the introduction points). A v3 descriptor contains: descriptor lifetime (typically 3 hours), list of introduction points with their Ed25519 identity keys and link specifiers, and the descriptor's outer signature (signed with the service's Ed25519 identity key). The descriptor content is encrypted: only clients who know the .onion address can decrypt the introduction point list. This encryption (using the .onion public key as the key agreement input) means that the HSDir relays storing the descriptor cannot read the list of introduction points - they see only encrypted data and the outer signature. The outer signature allows HSDirs to verify the descriptor is from the legitimate service owner, while the encrypted content prevents HSDirs from learning the introduction points.
HSDir Selection and the Time-Based Ring
HSDirs (hidden service directory relays) are a subset of Tor relays that have stored at least 96 hours of descriptors and have the HSDir flag from the directory authorities. At any given time, approximately 2,500-4,000 relays have the HSDir flag. Which HSDirs store a given service's descriptors is determined by a pseudorandom function of the service's public key and the current consensus period (6 hours). This means the responsible HSDirs rotate every 6 hours, and the specific HSDirs differ for each time period. The calculation uses the blinded public key (a time-variant derivative of the service's Ed25519 key) and the current SR (shared random) value from the consensus. This prevents an adversary from identifying and targeting the specific HSDirs responsible for a target service in advance - they change regularly and are determined by a value the adversary cannot predict.
Descriptor Publishing Process
The Tor daemon publishes descriptors as follows: it selects the 6 HSDirs responsible for the current and next consensus period (3 for each), constructs the descriptor, signs it, and uploads it to each HSDir. The upload uses Tor circuits to the HSDir relays so the HSDirs cannot determine the IP address of the service publishing to them. Descriptors are refreshed approximately every hour even if not changed (to reset the TTL). When the consensus period changes (every 6 hours), the responsible HSDirs change, and the Tor daemon automatically publishes to the new HSDirs. Monitor descriptor publishing in Tor logs with SafeLogging 0 and Log info: look for 'HS service [truncated address]: Successfully uploaded descriptor in: ...' messages. Failures appear as upload timeout or connection errors to specific HSDir fingerprints.
Client Descriptor Lookup Privacy
When a Tor client wants to connect to a .onion address, it must fetch the descriptor from HSDirs without revealing which .onion it is looking up. The client computes the responsible HSDirs using the same algorithm as the service (blinded public key + current SR value). The client then fetches the descriptor from one of the responsible HSDirs using a 3-hop Tor circuit. The HSDir sees the blinded public key (not the .onion address) and returns the encrypted descriptor. The client decrypts the descriptor using the .onion public key (which it knows from the .onion address). This design means: the fetching circuit guards do not know the .onion address being looked up, the HSDir sees only the blinded key (not the original key), and the descriptor content (introduction points) is only readable by clients who already know the .onion address.