Every naming system quietly answers two separate questions: what is this thing called, and can I trust that whatever answers to that name is the thing I meant? DNS answers the first. TLS and the certificate-authority system answer the second, bolted on decades later as a patch for a namespace never designed to authenticate anything. Onion addresses collapse both questions into one cryptographic operation. A Tor onion service’s 56-character .onion name is not a pointer to a public key — it is the public key, encoded. Resolve the name and you have already obtained the authenticated identity; there is no second step, no certificate to check, no authority to trust.
This piece covers what that unification buys, what it costs, and how far the pattern generalizes past Tor: the RFC that formally carved .onion out of the DNS root, the certificate that forced the standards process to move, the hash-ring mechanism that lets clients find a service with no directory to query, the key-blinding trick that keeps that ring from becoming a harvesting tool, and the honest limits of search and vanity naming in a space with no registry to walk.

🔗 Two Systems, Bolted Together: How DNS + PKI Actually Trust a Name
DNS resolves a name to an address: a resolver walks the hierarchy from root to TLD to authoritative server and hands back an IP. That step says nothing about identity — anyone who can poison a cache, hijack a resolver, or hijack a route to an authoritative server can make a name resolve to the wrong place. So a second, independent system exists to answer identity: a certificate authority signs a statement binding a public key to a domain name, and your TLS stack checks that signature against a trust store containing several hundred root and intermediate CAs — any one of which is a valid signer for any domain on the internet.
That “any CA can sign for any name” property is the load-bearing weakness of the model, and it’s a direct consequence of bolting two systems together after the fact: DNS has one trust root (the ICANN hierarchy), TLS has a separate, much larger one (the CA ecosystem), and a compromise anywhere in that second root — a stolen signing key, a socially engineered CA, a coerced certificate — produces output every major browser accepts without complaint. DNS itself has its own well-documented failure modes; PKI adds a second, larger attack surface rather than replacing the first. Two systems, two trust roots, two ways for a name to lie to you.
🔑 Collapsing Resolution and Authentication Into One Operation
Onion addresses take a different approach: instead of building a second system to authenticate the first system’s output, make the name itself unforgeable. A v3 address embeds a raw Ed25519 public key. Resolving it (computing where its descriptor lives and fetching it) and authenticating the service you reach (verifying it holds the matching private key) are the same act, because the name has no meaning independent of the key. There’s no separate binding step for an attacker to forge, because there’s nothing to bind — identifier and credential are one value.
This is a reusable pattern: the self-certifying identifier. Anywhere a system controls both the naming scheme and the identity scheme, it can ask whether those need to be two systems. IPFS content identifiers, SSH host-key fingerprints, git commit hashes, and Signal safety numbers are the same move applied elsewhere — a name derived directly from the thing it names, rather than one a separate authority vouches for. Public-key-based authentication does a version of it too: authenticate with a key directly rather than through a password intermediary a server has to store and can leak.

📜 RFC 7686 and the Certificate That Forced the Issue
.onion didn’t become exempt from DNS by Tor Project convention — it happened by IETF standards action. RFC 7686, “The ‘.onion’ Special-Use Domain Name,” published October 2015 and authored by Jacob Appelbaum (The Tor Project) and Alec Muffett (Facebook), registers .onion in the IANA Special-Use Domain Names registry created by RFC 6761, which requires any such registration to specify handling across seven categories: users, application software, name-resolution APIs, caching DNS servers, authoritative DNS servers, DNS server operators, and registrars. RFC 7686’s requirements follow directly: Tor-aware applications MUST treat .onion specially; other applications SHOULD fail rather than leak the name to public DNS; resolver APIs MUST resolve it per Tor’s own specs or return NXDOMAIN; DNS operators MUST NOT answer for it authoritatively; and registrars MUST NOT register it under any circumstance.
The timing had a concrete forcing function. In November 2014, DigiCert issued Facebook’s v2 address, facebookcorewwwi.onion, a publicly trusted EV certificate under the “Internal Name” class — the same class the CA/Browser Forum was banning outright, effective November 1, 2015. Because .onion had no formal domain status, CAs had no legitimate basis to keep issuing it certificates once internal-name certs were prohibited. RFC 7686, published weeks ahead of that deadline, gave .onion the special-use status CAs needed to keep treating it as a public name space — while permanently blocking any ICANN new-gTLD round from delegating .onion into the DNS root. A CA policy collision set the clock.
🔐 A v3 Address Is Not a Hash of a Key — It Is the Key
The 56-character base32 address is base32(pubkey ‖ checksum ‖ version). pubkey is the raw 32-byte Ed25519 public identity key. checksum is the first two bytes of SHA3-256(".onion checksum" ‖ pubkey ‖ version). version is a single byte, 0x03. That’s 35 bytes total, encoding to exactly 56 base32 characters. There’s no separate identity document and no trust-on-first-use step: knowing the address is knowing the authenticated public key, in full.

That construction is also why v3 is a real security upgrade, not just a longer string. v2 addresses were 80-bit truncated hashes of an RSA-1024 key — spoofable with enough compute against the hash. v3 carries the full Ed25519 key, so forging one means breaking the signature scheme at roughly 128-bit-class security, not finding a collision against a truncated 80-bit target.
| DNS + CA/PKI | Onion (v3) naming | |
|---|---|---|
| Resolution | Walk a hierarchy (root → TLD → authoritative) to an IP | Compute a hash-ring position from the address, fetch a descriptor |
| Authentication | Separate step: a CA-signed certificate binds key to name | Same step as resolution — the name is the key |
| Trust root | ICANN root (naming) + several hundred CAs (authentication) | None required — the address self-certifies |
| Who can impersonate | Any CA in the trust store can mis-issue for any domain | No one can mint a valid address without the private key |
| Typical failure mode | Cache poisoning, registrar hijack, CA mis-issuance | None of the above; cost shifts to memorability and lookalike phishing |
| Revocation | CRL / OCSP, reissuance | None — a new key is a new identity, not a rotation of the old one |
📐 Zooko’s Triangle and the Price of a Self-Certifying Name
This isn’t free, and the cost is exactly what Zooko Wilcox-O’Hearn’s conjecture predicts: a naming system can have at most two of three properties — human-meaningful, secure, decentralized. DNS + PKI is human-meaningful and (with a functioning CA ecosystem) secure, but not decentralized — it depends on registrars, a root, and a small set of trusted CAs. Onion addresses are secure and decentralized — no registrar, no CA, the name self-certifies — but they give up memorability entirely. A raw v3 address is unrecognizable to a human without a bookmark.
Aaron Swartz’s 2011 essay on “squaring” the triangle argued the way out isn’t a protocol change — it’s a local, non-authoritative alias layer on top of a secure, decentralized base. The ecosystem converged on that independently: SecureDrop’s Onion Names, introduced October 2020, let Tor Browser resolve curated aliases to the real 56-character address via a maintained mapping list fetched client-side, with the address still doing all the cryptographic work. It’s a petname system, not a naming-protocol change — security lives entirely in the key, and a user could decline the alias without losing anything. That constraint generalizes: when you’re tempted to bolt friendly names onto a self-certifying identifier scheme, keep the alias layer strictly optional. If the alias service goes down or is compromised, the base layer’s guarantees must be unaffected.

🕸️ Finding a Service With No Directory: The HSDir Ring
Self-authentication solves identity, not discovery — something still has to tell a client where to fetch a service’s introduction points, with no central index to ask. Every onion service periodically uploads a signed, encrypted descriptor to a rotating subset of relays acting as HSDirs (hidden-service directories), a role any sufficiently stable, well-behaved relay can opt into.
Placement is computed, not registered, and it’s worth being precise: this is consistent hashing over the consensus-published relay set, not a Kademlia-style DHT. There’s no gossip discovery and no iterative multi-hop lookup — every participant already has the same complete input, the current consensus, from which to compute positions locally. Tor’s directory authorities jointly generate a fresh shared random value each period. From that, every relay computes each HSDir’s ring index as SHA3-256("node-idx" ‖ node_identity ‖ shared_random_value ‖ period_num ‖ period_length), and where a given descriptor belongs as SHA3-256("store-at-idx" ‖ blinded_pubkey ‖ replica_num ‖ period_length ‖ period_num). A service and a client who’ve never communicated land on the same HSDirs because both run the identical deterministic computation over identical public inputs, not because either queried a registry.
Current consensus defaults — worth stating precisely, and re-checking against spec.torproject.org rather than treating as permanent — are hsdir_n_replicas = 2, hsdir_spread_store = 4 (each replica uploaded to the four HSDirs following its index — eight uploads total), and hsdir_spread_fetch = 3 (a client tries up to three HSDirs per replica). The ring rotates every 1,440 minutes by current default, so no fixed set of HSDirs permanently owns a service’s descriptor.
Name the hybrid explicitly: HSDirs are a genuinely open, permissionless set of storage nodes, but their positions derive from randomness a small set of directory authorities jointly generate. Don’t mistake “no single directory holds all the data” for “no trusted coordination exists anywhere” — a hash ring can be decentralized in storage while centrally coordinated in the randomness that determines placement.

🌀 Key Blinding: Storing the Descriptor Without Learning the Address
Publishing to semi-trusted storage only stays safe if those nodes can hold a descriptor without learning who the service is. v3 achieves that with key blinding: rather than signing and indexing descriptors under the real identity key, the service derives a blinded keypair fresh each period — blinding factor h = SHA3-256("Derive temporary signing key" ‖ A ‖ nonce) (clamped per Ed25519), blinded public key A' = h·A. That’s a one-way elliptic-curve scalar multiplication: anyone who already knows real key A can recompute A' for any period, but recovering A from A' alone means solving discrete log — infeasible. A subcredential, SHA3-256("subcredential" ‖ credential ‖ A') where credential = SHA3-256("credential" ‖ A), further gates the descriptor’s inner encryption. Net effect: an HSDir only ever sees a rotating, unlinkable blinded key — never the real address — unless a client who already knows the real address shows up and asks.
This closes a specific, documented v2 weakness. v2 derived its directory position from the unblinded service identifier, and the descriptor a v2 HSDir stored either contained the real address in the clear once decrypted or, in earlier deployments, was directly recoverable. An adversary running enough Sybil relays to cover a slice of the v2 keyspace could passively harvest active v2 addresses simply by being selected as an HSDir for them — no cryptography broken, the protocol just handed the address to whoever the ring routed it to. Tor ticket #8106 (2013) documented this originally; academic work — “Improving the Privacy of Tor Onion Services,” IACR ePrint 2022/407 — treats it as a concrete motivation for the v3 redesign, alongside RSA-1024/SHA-1’s thin margins. v2 was deprecated in 2020, removed from the codebase in 2021; every v2 mechanic above is historical.

| v2 (removed from codebase, 2021) | v3 (current) | |
|---|---|---|
| Address length | 16 characters | 56 characters |
| Identity key | RSA-1024 | Ed25519 (256-bit) |
| Address construction | Truncated hash of the public key | Raw public key + checksum + version, base32-encoded |
| Security margin | ~80-bit, weakened further by truncation | ~128-bit-class |
| What an HSDir sees | The real, unblinded identifier — enumerable (ticket #8106) | A per-period blinded key, unlinkable across periods |
| Status | Deprecated 2020, removed 2021 | Current default |
🔒 Client Authorization: A Second, Optional Gate
Self-authentication answers “is this really the service I think it is,” not “should this client reach it at all” — that’s client authorization, an opt-in restricted-discovery control. An operator generates a random 32-byte descriptor-encryption key and encrypts it separately to each authorized client’s x25519 public key via .auth files; the resulting descriptor carries two layers of encryption. Without the matching private key — kept client-side in a .auth_private file — a client, an HSDir, or a passive observer that fetches the descriptor gets ciphertext, not even the introduction-point list.
This decouples “can compute the name” from “can reach the service”: knowing the address is necessary but no longer sufficient. It’s capability-based access control layered above a self-authenticating name, not a password check bolted onto the application layer — and it’s opt-in per service, not something most onion services enable.
🔍 Why Search Over Onion Space Is Necessarily Partial
Naming without a registry has a direct consequence for search: there’s nothing to enumerate. No zone file to walk, no registrar database to query. Any onion search engine is limited to what it’s told about or discovers by crawling links between pages it already knows — partial coverage is structural, not a shortfall.
Ahmia, founded and maintained by Juha Nurmi, runs an open-source crawler-and-index stack that follows links between known onion pages, respects robots.txt, accepts voluntary “Add Service” submissions, and maintains a self-reported content blocklist. DuckDuckGo’s onion service is a different thing and shouldn’t be conflated with it: it’s DuckDuckGo’s regular clearnet search index, reachable over Tor for transport-layer privacy — not an index of onion sites. (Onion addresses can be regenerated by their operators, so this piece won’t quote a specific string for DuckDuckGo’s — confirm the current one against DuckDuckGo’s own documentation.) Neither tool, nor any combination, can claim completeness. A service never linked to and never self-submitted is invisible by construction — the naming system working as intended, not a search-engine failure. In a namespace with the same no-registry property, “discoverable only via out-of-band sharing” is a design choice about who finds what, not a missing feature.
🎭 Vanity Addresses: Grinding the Keyspace, Not Weakening It
mkp224o, written by cathugger, generates Ed25519 keypairs and checks each base32-encoded public key for a target prefix, keeping only matches. Base32 excludes 0, 1, 8, 9, so only 32 possible characters exist per position; commodity hardware tests on the order of hundreds of millions of candidates per second, making a 6-character prefix a matter of minutes and a 7–8 character prefix hours to days, cost growing exponentially per added character.
Grinding for a prefix changes nothing about the resulting key’s security — every candidate is a fully random, independently generated keypair, and only cosmetic matches are kept. The keyspace isn’t reduced. The risk is social: an attacker can grind a similar-looking prefix as cheaply as a legitimate operator grinds a memorable one — raw material for a convincing phishing lookalike. A matching prefix is never an authentication signal — only the full 56 characters, or a verified bookmark or link, is worth trusting. Generalize the caution past Tor: any scheme where users eyeball-match a partial identifier is exactly as cheap for an attacker to spoof as for a legitimate operator to generate.
🧩 Retrofitting Trust: Onion-Location and RFC 9799
Two pieces of infrastructure bridge onion naming back into mainstream web plumbing that never expected it. The Onion-Location HTTP response header — Onion-Location: http://<address>.onion<path>, or an equivalent <meta http-equiv="onion-location"> tag — lets a clearnet HTTPS site advertise its onion mirror. Tor Browser has supported it since version 9.5 (2020), surfacing a UI affordance offering the switch, and requires the header served over HTTPS with the advertising page not itself an onion service. Freedom of the Press Foundation’s Secure The News project tracks adoption via that header and, in its most recent published check, found only a handful of major outlets — The New York Times, ProPublica, Deutsche Welle, and taz — actively advertising onion mirrors, well behind HTTPS adoption generally. SecureDrop, used by many of those same newsrooms, is the canonical onion-only use case: self-authenticating naming removes the need for a source to trust a registrar or CA at all.

RFC 9799, published June 2025, tackles the opposite direction: getting a conventional TLS certificate issued to an onion address, for tooling that still expects one. It standardizes ACME extensions — new challenge types (onion-csr-01, plus modified http-01/tls-alpn-01 variants) and in-descriptor CAA records — because DNS-based domain validation, the mechanism ACME normally relies on, is structurally impossible for a name deliberately kept out of DNS. Worth being precise about the problem this solves: the onion address already self-authenticates the service the moment it resolves. A certificate on top mainly serves browser UX and non-Tor-aware tooling — not a security gap in the onion layer itself. Two authentication systems stacking, where only one was strictly necessary.
🧭 What This Means for You
The lesson generalizes past Tor: naming and authentication are, by default, two systems with two trust roots and two failure modes — a design decision, not a law of nature. Anywhere you control both schemes for a system you’re building, ask whether they need to stay separate. A self-certifying identifier — a content hash, a public key, a commit hash — collapses “what is this called” and “can I trust it” into one operation, eliminating a class of impersonation attack by construction rather than by policy.
That collapse isn’t free. You give up memorability, and the honest fix is a strictly optional, non-authoritative alias layer — never a change to the base naming scheme. If storage nodes in your system are only semi-trusted, ask whether the routing key you hand them can be derived one-way from the real identifier, rather than being or revealing it — that turns “can enumerate the directory” into “can only see what it’s already been handed.” Periodic rotation to limit correlation carries a real cost, too: it forces every participant to agree on “the current period,” a consensus/clock-sync dependency easy to underestimate on a whiteboard.
📚 Further Reading
- What Is the Domain Name System? — the baseline resolution model onion naming routes around.
- DNS Security Issues, Vulnerabilities, and Exploits — the failure modes a self-certifying name eliminates by construction.
- Passkey vs Password Manager: Do You Need Both? — the same “authenticate with a public key directly” move, applied to logins.
- IPFS? What Is the InterPlanetary File System? — another self-certifying identifier scheme (content hashes instead of keys), same underlying pattern.
- Primary sources: RFC 7686, RFC 6761, RFC 9799, and the Tor Project’s rend-spec-v3 (see the key-blinding appendix and HSDir descriptor spec).
❓ Frequently Asked Questions
What is an onion address, technically?
A 56-character base32 string encoding a raw 32-byte Ed25519 public key, a two-byte checksum, and a version byte — base32(pubkey ‖ checksum ‖ version). It isn’t a hash or a pointer to a key; the address contains the key, so resolving it and authenticating the service happen in one step.
Why can’t I register a custom .onion domain the way I’d register a .com?
Because .onion was deliberately removed from the domain-registration system. RFC 7686 registers it as special-use under RFC 6761 and requires registrars to refuse any registration request — an onion address is generated locally from a keypair, not allocated by an authority.
Is the HSDir ring a distributed hash table like Kademlia?
No. It’s consistent hashing over the current consensus-published relay set — every relay computes ring positions locally from public inputs rather than discovering them through gossip or iterative lookups the way a Kademlia-style DHT does.
Can two people accidentally generate the same onion address?
No — Ed25519’s full keyspace is far too large for accidental collision. The only “collision” seen in practice is deliberate: grinding for a matching prefix with a tool like mkp224o, which finds a lookalike, not a duplicate.
If an onion address matches the prefix I expected, is that proof I’ve reached the right service?
No. A matching prefix costs an attacker exactly what it costs a legitimate operator to grind. Prefix-matching is a phishing vector, not an authentication check — only the full 56-character address, or a link verified through another channel, should be trusted.
Do onion services need a TLS certificate?
Not for the naming system’s security — the address already self-authenticates the service to any Tor-aware client. A certificate, issuable via RFC 9799’s ACME extensions (published June 2025), mainly matters for browser UX and tooling that isn’t Tor-aware.
📚 Recommended Resources
Disclosure: some links below are Amazon affiliate links. If you buy through them, I earn a small commission — at no extra cost to you — which helps keep this site running.
Serious Cryptography: A Practical Introduction to Modern Encryption
Jean-Philippe Aumasson · Book · 2nd edition (2024)
The clearest available treatment of the elliptic-curve and hashing primitives underneath v3 onion addressing — Ed25519, key blinding, and why a public key can safely double as a name.
Cryptography Engineering: Design Principles and Practical Applications
Niels Ferguson, Bruce Schneier & Tadayoshi Kohno · Book
The standard reference for how primitives get assembled into real protocols, and where that assembly usually goes wrong. Directly relevant to the naming-versus-authentication split this article picks apart.
Designing Data-Intensive Applications
Martin Kleppmann & Chris Riccomini · Book · 2nd edition (2026)
For the distributed-systems half of the story: consistent hashing, replication, and how a system agrees on who holds what — the general form of the HSDir ring described above.
Free and primary: RFC 7686 (the .onion special-use reservation) and the Tor rendezvous specification at spec.torproject.org.