Recently I noticed that all the V3 addresses end in "d". Some examples from Ahmia.fi search results ("Tor" was the search query):

  1. 2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion
  2. pzhdfe7jraknpj2qgu5cz2u3i4deuyfwmonvzu5i3nyw4t4bmg7o5pad.onion
  3. rzuwtpc4wb3xdzrj3yeajsvm3fkq4vbeubm2tdxaqruzzzgs5dwemlad.onion

To make sure the story is correct, I made another test using mkp224o for creating custom V3 addresses (in this example I've generated addresses starting with test):

All V3 addresses ending with d

As another interesting result two ending letters as:

  1. ad
  2. id
  3. yd
  4. qd

Then I checked Tor Spec for v3 in here: https://github.com/torproject/torspec/blob/main/rend-spec-v3.txt. This is the exact copy of section 6 (Encoding Onion Address):

  1. Encoding onion addresses [ONIONADDRESS]

The onion address of a hidden service includes its identity public key, a version field and a basic checksum. All this information is then base32 encoded as shown below:

onion_address = base32(PUBKEY | CHECKSUM | VERSION) + ".onion"
CHECKSUM = H(".onion checksum" | PUBKEY | VERSION)[:2]

  - PUBKEY is the 32 bytes ed25519 master pubkey of the hidden service.
  - VERSION is a one byte version field (default value '\x03')
  - ".onion checksum" is a constant string
  - CHECKSUM is truncated to two bytes before inserting it in onion_address

Here are a few example addresses:


For more information about this encoding, please see our discussion thread at [ONIONADDRESS-REFS].

All the examples are ended with d as I made them bold!

The documentation exactly says that: onion_address = base32(PUBKEY | CHECKSUM | VERSION) + ".onion"

Therefore, base32 of "PUBKEY | CHECKSUM | VERSION" is always ending with d? Or ad, id, qd, and yd?

I also checked https://lists.torproject.org/pipermail/tor-dev/2017-January/011816.html and https://lists.torproject.org/pipermail/tor-dev/2016-December/011734.html

1 Answer 1


This is just how the base-32 conversion works out when the last byte is 0x03 (the version byte). For example, see the following base-32 conversions:

0x0000000000 = AAAAAAAA
0x0000000003 = AAAAAAAD
0x0000000103 = AAAAAAID
0x0000000203 = AAAAAAQD
0x0000000303 = AAAAAAYD
0x0000000403 = AAAAABAD
0x0000000503 = AAAAABID
0x0000000603 = AAAAABQD

In base-32, each 5 bits are mapped to a letter. The last byte (8 bits) is 0x03 = 0b00000011, so the last letter will take 5 of those bits (0b00011 is D), and the 3 other bits 0b000 go towards the second last letter. So for the second last letter, there are only 2 bits that can change, so there are only 4 possible letters for the second last letter (0b00000 is A, 0b01000 is I, 0b100000 is Q, and 0b11000 is Y). For the bytes 0x0000000103, the last 10 bits are 0b0100000011. Of those 10 bits, the first 5 0b01000 (decimal 8) map to I and the second 5 0b00011 (decimal 3) map to D.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .