Tor Onion v3 Vanity Address


mkp224o is a vanity address generator for Tor Onion v3 Hidden Services, created by cathugger and available on Github.

The mkp224o repository on cathugger's GitHub account.

Tor Proposal 224 is the proposal for the new Onion v3 specification, so that's what mkp224o was named after.

mkp224o is very easy to install and run. Download and extract the latest version from GitHub, then on Debian-based systems, you can use:

#Install dependencies if required
sudo apt-get install autoconf libsodium-dev


You can run "./mkp224o -h" to view the available options:

js@node0:~/onionv3/mkp224o$ ./mkp224o
Usage: ./mkp224o filter [filter...] [options]
       ./mkp224o -f filterfile [options]
	-h  - print help
	-f  - instead of specifying filter(s) via commandline, specify filter file which contains filters separated by newlines
	-q  - do not print diagnostic output to stderr
	-x  - do not print onion names
	-o filename  - output onion names to specified file
	-F  - include directory names in onion names output
	-d dirname  - output directory
	-t numthreads  - specify number of threads (default - auto)
	-j numthreads  - same as -t
	-n numkeys  - specify number of keys (default - 0 - unlimited)
	-N numwords  - specify number of words per key (default - 1)
	-z  - use faster key generation method. this is now default
	-Z  - use slower key generation method
	-s  - print statistics each 10 seconds
	-S t  - print statistics every specified amount of seconds
	-T  - do not reset statistics counters when printing

You can then run mkp224o to search for an address. The "-S" argument will make mkp224o output statistics every 5 seconds, and the "-d" argument allows you to specify a directory to store the generated keys.

js@node0:~/onionv3/mkp224o$ ./mkp224o -S 5 -d onions jamie
set workdir: onions/
sorting filters... done.
in total, 1 filter
using 4 threads
>calc/sec:17035.009192, succ/sec:0.000000, rest/sec:39.964831, elapsed:0.100088sec
>calc/sec:22250.236672, succ/sec:0.000000, rest/sec:0.000000, elapsed:5.103855sec
>calc/sec:22272.487630, succ/sec:0.000000, rest/sec:0.000000, elapsed:10.107517sec
>calc/sec:22256.077578, succ/sec:0.000000, rest/sec:0.000000, elapsed:15.111813sec
>calc/sec:22278.089855, succ/sec:0.000000, rest/sec:0.000000, elapsed:20.116102sec
>calc/sec:22253.435622, succ/sec:0.000000, rest/sec:0.000000, elapsed:25.120363sec
>calc/sec:21762.771552, succ/sec:0.000000, rest/sec:0.000000, elapsed:30.142012sec
>calc/sec:22258.870726, succ/sec:0.000000, rest/sec:0.000000, elapsed:35.146309sec
>calc/sec:22282.575137, succ/sec:0.000000, rest/sec:0.000000, elapsed:40.150578sec
>calc/sec:22258.577166, succ/sec:0.000000, rest/sec:0.000000, elapsed:45.154941sec
>calc/sec:22198.079226, succ/sec:0.000000, rest/sec:0.000000, elapsed:50.159383sec
>calc/sec:22253.661568, succ/sec:0.000000, rest/sec:0.000000, elapsed:55.163728sec
>calc/sec:22276.712822, succ/sec:0.000000, rest/sec:0.000000, elapsed:60.168057sec
>calc/sec:22254.261335, succ/sec:0.000000, rest/sec:0.000000, elapsed:65.172357sec
>calc/sec:22277.632325, succ/sec:0.000000, rest/sec:0.000000, elapsed:70.176659sec
>calc/sec:22256.428313, succ/sec:0.000000, rest/sec:0.000000, elapsed:75.180966sec
^Cwaiting for threads to finish... done.

In the example above, I exited mkp224o after 75 seconds using Ctrl+C.

Matching addresses are automatically saved into either the directory where mkp224o is running or the one specified using the "-d" switch.

js@node0:~/onionv3/mkp224o$ ls onions/ | head -n 5

js@node0:~/onionv3/mkp224o$ ls jamie22ezawwi5r3o7lrgsno43jj7vq5en74czuw6wfmjzkhjjryxnid.onion/
hostname  hs_ed25519_public_key  hs_ed25519_secret_key

You could also set up a cronjob to run mkp224o at boot in a detached screen session:

@reboot cd /path/to/mkp224o && screen -dmS onionv3 ./mkp224o -S 600 -d onions jamie

You can then check up on mkp224o using "screen -r onionv3". Use Ctrl+A followed by Ctrl+D to detach from a screen session without terminating it.


Running on a Raspberry Pi 2B, mkp224o achieved a pretty consistent 22,200 calculations per second, with 1 filter running on 4 threads.

The 4 Raspberry Pi Zeros all achieved around 4,180 calculations per second, with 1 filter running on 1 thread.

mkp224o ran 24 hours a day for 21 days. The total number of addresses generated by each device is shown below:

Master (RPi 2B)   : 1014
Node 1 (RPi Zero) : 222
Node 2 (RPi Zero) : 192
Node 3 (RPi Zero) : 212
Node 4 (RPi Zero) : 235

This makes for a total of 1,875 addresses, which is roughly 1 matching address found every 16 minutes and 8 seconds, or 967.68 seconds.

Address Generation Times

In order to get a very rough estimate for the address generation time for each vanity length, I used the total generation time for the 1,875 addresses that I generated over 21 days, and extrapolated that using the total number of possible characters (32, a-z, 2-7) in order to get values for other vanity address lengths.

These values are estimated using combined data from mkp224o running on 1 Raspberry Pi 2B and 4 Raspberry Pi Zeros, simultaneously and 24/7 for 21 days.

Vanity Characters : Approximate Generation Time
1  : <1 second
2  : <1 second
3  : 1 second
4  : 30 seconds
5  : 16 minutes
6  : 8.5 hours
7  : 11.5 days
8  : 1 year
9  : 32 years
10 : 1,024 years
11 : 32,768 years
12 : 1 million years
13 : 32 million years
14 : 1 billion years
15 : 32 billion years
16 : 1 trillion years
17 : 32 trillion years
18 : 1 quadrillion years
19 : 32 quadrillion years
20 : 1 quintillion years
21 : 32 quintillion years
22 : 1 sextillion years
23 : 32 sextillion years
24 : 1 septillion years
25 : 32 septillion years
26 : 1 octillion years
27 : 32 octillion years
28 : 1 nonillion years
29 : 32 nonillion years
30 : 1 decillion years
31 : 32 decillion years
32 : 1 undecillion years
33 : 32 undecillion years
34 : 1 duodecillion years
35 : 32 duodecillion years
36 : 1 tredecillion years
37 : 32 tredecillion years
38 : 1 quattuordecillion years
39 : 32 quattuordecillion years
40 : 1 quindecillion years
41 : 32 quindecillion years
42 : 1 sexdecillion years
43 : 32 sexdecillion years
44 : 1 septendecillion years
45 : 32 septendecillion years
46 : 1 octodecillion years
47 : 32 octodecillion years
48 : 1 novemdecillion years
49 : 32 novemdecillion years
50 : 1 vigintillion years
51 : 32 vigintillion years
52 : 10^66 years
53 : 10^69 years
54 : 10^72 years
55 : 10^75 years
56 : 10^78 years (1,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000)

A copy of this is available on my Pastebin if you wish to view it without scrolling:

I think that 11 vanity characters is realistically achievable given enough computing power, for example when/if Facebook upgrade their hidden service to Onion v3. The Raspberry Pi cluster that I used is a very low performance device when compared to a dedicated GPU crypto rig.

Filtering Generated Addresses

After I had been running mkp224o for 21 days, I needed to use the cluster for something else so it was time to choose an address. Glancing through the results, there wasn't anything that stood out, so I searched through it with grep for various keywords and acronyms (eg: sec, pgp, php, etc), however there wasn't anything particularly good.

I wanted to search for English words in the output, so I used the /usr/share/dict/british-english file that is included with the package "wbritish" on Debian-based systems.

At first I tried the following, but it turned out to be extremely inefficient and could cause a system crash, so I do not recommend trying this yourself!

#Install wbritish if required
sudo apt-get install wbritish

#Make a copy of the british-english dictionary for searching
cp /usr/share/dict/british-english wordlist.txt

#Remove one character words
grep -v "^[A-Za-z]$" wordlist.txt > wordlist2.txt

#Remove two character words
grep -v "^[A-Za-z][A-Za-z]$" wordlist2.txt > wordlist.txt

#Remove "onion", "Onion", "Jamie", "ion", "Jami", "jam" & "Amie"
egrep -v "(^onion$|^Onion$|^ion$|^Jamie$|^Amie$|^Jami$|^jam$)" wordlist.txt > wordlist2.txt

#Find words from wordlist2.txt in onion-v3-export.txt
This could crash your system, be careful!
grep -iFf wordlist2.txt onion-v3-export.txt

The reason that this technique is so inefficient is that it uses just one instance of grep for the entire search, and grep isn't designed to handle that. I had this running for around 5 minutes and it slowly built up 16 GB RAM usage and started eating into my swap partition, which isn't good! Grep isn't designed for handling this sort of processing, so it's unfair to discount it for this memory-handling behaviour.

The technique that worked well was using a separate instance of grep for each word to search for, instead of trying to search for them all at once. This was a slower searching method, however it uses minimal memory.

I also decided to cut the addresses to search down to just the first 12 characters, as words that aren't at the start of the address aren't of much value in most cases.

cut -c 1-12 onion-v3-export.txt > onion-cut.txt

Then use a simple bash for loop in order to check each of the dictionary words against the address list individually:

for word in `cat wordlist2.txt`; do grep --colour=always -i "$word" onion-cut.txt; done

I set this running on a Raspberry Pi 2B and it took around 5 hours to search 1875 addresses for around 90,000 dictionary words.

The output can be seen below:


On a side note, in order to generate HTML output of the ANSI-encoded terminal emulator colours, you can use the "aha" command:

for word in `cat wordlist4.txt`; do grep --colour=always -i "$word" onion-cut.txt; done | aha

...which will convert the input into HTML with inline colour styling and the following header:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<!-- This file was created with the aha Ansi HTML Adapter. -->
<html xmlns="">
<meta http-equiv="Content-Type" content="application/xml+xhtml; charset=UTF-8" />

I then edited out the inline styling and used my CSS file instead in order to be compliant with my Content-Security-Policy.

A significantly better way of filtering the vanity addresses would have been putting them all into a database and querying it, as database software is highly optimised for handling this sort of computation.

I was really hoping to get a ^jamieweb address to go along with my Onion v2 service jamiewebgbelqfno.onion, however with Onion v3 and mkp224o, my estimates show that would take around a year. With Onion v2 and Shallot, that would (and did) take around 25 days.

Honourable Mentions:

jamie4debrkhllykiyiztbpg6fokecmzhxvj4buig5qss5m4wasn5yyd.onion - Debian?
jamiedgraphfwrf2mfhc4iprjjpgzapiqikjxz4yseodq2bvnqcicoad.onion - Fast Graph Database?
jamiedigjmx56qpxfwht6pniy2jibt6lpled4juja3wmyuk7bfeaczad.onion - DNS Lookup Utility?
jamieoslok3jxyg223xdm2fftsdd33cio2p5hozkipj27wcygomy4yid.onion - Capital of Norway?
jamietap7o7pux6fxpnxrbqvto6dypr3tx3befc7bpon6gn5m4tsftqd.onion - Network Tap?

The full list of generated addresses is available on my Pastebin:


As of writing this, Onion v3 support is only available alpha versions of Tor, however a Tor build with Onion v3 functionality is currently at the second release candidate, so it should be reaching the stable branch very soon.

For as long as Tor Onion v3 functionality remains in alpha only, I will be keeping the current hidden service address (http://32zzibxmqi2ybxpqyggwwuwz7a3lbvtzoloti7cxoevyvijexvgsfeid.onion) as well as running the Tor alpha instance on a separate, isolated server.

When Onion v3 hits Tor stable, I will move it across to a main server as well as start using the jamie3vkiwi vanity address. I will also continue hosting my Onion v2 hidden service for as long as it is safe to do so.

Luckily it is very easy to host multiple hidden services using the same Tor instance. In your torrc, just add multiple hidden service configurations:

HiddenServiceDir /desired/path/to/v3/hidden/service/config
HiddenServiceVersion 3
HiddenServicePort <localport> <server>

HiddenServiceDir /desired/path/to/v2/hidden/service/config
HiddenServiceVersion 2
HiddenServicePort <localport> <server>

Other Onion v3 Vanity Address Generation Programs

In addition to mkp224o by cathugger (which is what I used), there are also other Onion v3 vanity address generation programs out there:

I personally tried out oniongen-go and oniongen-c in addition to mkp224o.

If I have missed any, please let me know.


To conclude, I think that mkp224o is fantastic software that worked stably for prolonged amounts of time on low-end hardware. If you want to generate a vanity address for your own Onion v3 service, definitely check out mkp224o.

I am definitely not as happy with my Onion v3 vanity address as I am with my Onion v2 vanity address, however due to the enormously increased cryptographic security of Onion v3, vanity address generation takes slightly longer. This is not a problem for me though, since security is always more important that vanity, especially with software like Tor.

From:On DarkNet – Dark Web News and Analysis
Copyright of the article belongs to the author, please do not reproduce without permission.

<<Pre Post
Next Post>>