Skip to content

AlexanderYastrebov/onion-vanity-address

Repository files navigation

onion-vanity-address ๐Ÿง…

This tool generates Tor Onion Service v3 vanity address with a specified prefix.

It can also generate vanity client authorization keypair.

Compared to similar tools, it uses the fastest search algorithm ๐Ÿš€

Usage

Install the tool locally and run:

go install github.com/AlexanderYastrebov/onion-vanity-address@latest
$ onion-vanity-address allium
Found allium... in 12s after 558986486 attempts (48529996 attempts/s)
---
hostname: alliumdye3it7ko4cuftoni4rlrupuobvio24ypz55qpzjzpvuetzhyd.onion
hs_ed25519_public_key: PT0gZWQyNTUxOXYxLXB1YmxpYzogdHlwZTAgPT0AAAAC1ooweCbRP6ncFQs3NRyK40fRwaodrmH572D8py+tCQ==
hs_ed25519_secret_key: PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAAAQEW4Rhot7oroPaETlAEG3GPAntvJ1agF2c7A2AXmBW3WqAH0oUZ1hySvvZl3hc9dSAIc49h1UuCPZacOWp4vQ

or use the Docker image:

docker pull ghcr.io/alexanderyastrebov/onion-vanity-address:latest
docker run  ghcr.io/alexanderyastrebov/onion-vanity-address:latest allium

To configure hidden service keypair decode base64-encoded secret key into hs_ed25519_secret_key file, remove hs_ed25519_public_key and hostname files and restart Tor service:

$ echo PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAAAQEW4Rhot7oroPaETlAEG3GPAntvJ1agF2c7A2AXmBW3WqAH0oUZ1hySvvZl3hc9dSAIc49h1UuCPZacOWp4vQ | base64 -d > /var/lib/tor/hidden_service/hs_ed25519_secret_key

$ rm /var/lib/tor/hidden_service/hs_ed25519_public_key
$ rm /var/lib/tor/hidden_service/hostname
$ systemctl reload tor

$ cat /var/lib/tor/hidden_service/hostname
alliumdye3it7ko4cuftoni4rlrupuobvio24ypz55qpzjzpvuetzhyd.onion

Multiple prefixes

The tool can check multiple prefixes simultaneously:

onion-vanity-address zwiebel cipolla cebolla

It will output the first onion address that starts with any of the specified prefixes. When searching for multiple prefixes of varying lengths, shorter prefixes will appear more often across multiple runs.

Client authorization

To generate vanity client authorization keypair use --client flag:

$ onion-vanity-address --client LEMON
Found LEMON... in 0s after 14990923 attempts (63626192 attempts/s)
---
public_key: LEMON7P5L7FEZZEJJGQTC3PDFRHEOOBP3H2XXHRFQSD72OKKEE5Q
private_key: AAADDFICRR46KLA52KV2QRIN6GUWIPEIVZZZUVZLC5UVE53QNMTA

then add public key to authorized_clients directory:

$ echo descriptor:x25519:LEMON7P5L7FEZZEJJGQTC3PDFRHEOOBP3H2XXHRFQSD72OKKEE5Q > /var/lib/tor/hidden_service/authorized_clients/lemon.auth
$ systemctl reload tor

To access the service via Tor Browser provide it the private key:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
โ”‚ ๐Ÿ›ˆ Authentication required   ๐Ÿ—™ โ”‚ ๏ผ‹
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
โ”‚ โ† โ†’ โŸณ ๐Ÿ›ˆ ๐Ÿ— alliumdye3it7ko4cuftoni4rlrupuobvio24ypz55qpzjzpvuetzhyd.onion
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
โ”‚                                                       โ”‚
โ”‚  The onion site allium...etzhyd.onion is requesting   โ”‚
โ”‚  that you authenticate.                               โ”‚
โ”‚                                                       โ”‚
โ”‚  โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ”‚
โ”‚  โ”‚ AAADDFICRR46KLA52KV2QRIN6GUWIPEIVZZZUVZLC5UVE...โ”‚  โ”‚
โ”‚  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ”‚
โ”‚   โ–ก Remember this key          โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ  โ”‚
โ”‚                                โ”‚  Cancel  โ”‚ โ”‚  OK  โ”‚  โ”‚
โ”‚                                โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ  โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

To see all flags and usage examples run:

onion-vanity-address --help

Performance

The tool checks ~45'000'000 keys per second on a laptop:

$ onion-vanity-address --timeout 20s goodluckwiththisprefix
Stopped searching goodluckwiththisprefix... after 20s and 959763220 attempts (47985799 attempts/s)

which is ~2x faster than mkp224o:

$ timeout 20 docker run ghcr.io/cathugger/mkp224o:master -s -y goodluckwiththisprefix
sorting filters... done.
filters:
        goodluckwiththisprefix
in total, 1 filter
using 8 threads
>calc/sec:18497645.320881, succ/sec:0.000000, rest/sec:79.315507, elapsed:0.100863sec
>calc/sec:18884429.043617, succ/sec:0.000000, rest/sec:0.000000, elapsed:10.108983sec

In practice, it finds a 6-character prefix within a minute. Each additional character increases search time by a factor of 32.

Kubernetes

Run distributed vanity address search in Kubernetes cluster using the demo-k8s.yaml manifest without exposing the secret key to the cluster:

$ # Locally generate secure starting keypair (or use existing one created by Tor)
$ onion-vanity-address start
Found start... in 1s after 26921387 attempts (43429741 attempts/s)
---
hostname: startxxytwan7gfm6ojs6d2auwhwjhysjz3c5j2hd7grlokzmd4reoqd.onion
hs_ed25519_public_key: PT0gZWQyNTUxOXYxLXB1YmxpYzogdHlwZTAgPT0AAACUwRne+J2A35is85MvD0Clj2SfEk52LqdHH80VuVlg+Q==
hs_ed25519_secret_key: PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAABgZ5a7kuS0N1jaA12gtsqI87RPS1eqSj4KWpwXukWtV7pFj6gS200J96P8JDWTpvx000KF3r4l+xYcIJszhPZk

$ # Edit demo-k8s.yaml to configure prefix, starting **public key**, parallelism, and resource limits ๐Ÿ’ธ

$ # Create search job
$ kubectl apply -f demo-k8s.yaml
job.batch/ova created

$ # Check the job
$ kubectl get job ova
NAME   STATUS    COMPLETIONS   DURATION   AGE
ova    Running   0/999999      5s         5s

$ # Check pods
$ kubectl get pods --selector=batch.kubernetes.io/job-name=ova
NAME          READY   STATUS    RESTARTS   AGE
ova-0-tz27j   1/1     Running   0          7s
ova-1-zwlhl   1/1     Running   0          7s
ova-2-khl7f   1/1     Running   0          7s
ova-3-9l4z5   1/1     Running   0          7s
ova-4-tbx2m   1/1     Running   0          7s
ova-5-mpsz8   1/1     Running   0          7s
ova-6-xg7ft   1/1     Running   0          7s
ova-7-6zcn8   1/1     Running   0          7s
ova-8-cqrtj   1/1     Running   0          7s
ova-9-dtqhc   1/1     Running   0          7s

$ # Check resource usage
$ kubectl top pods --selector=batch.kubernetes.io/job-name=ova

$ # Wait for the job to complete
$ kubectl wait --for=condition=complete job/ova --timeout=1h
job.batch/ova condition met

$ # Job is complete
$ kubectl get job ova
NAME   STATUS     COMPLETIONS   DURATION   AGE
ova    Complete   1/999999      23m14s     23m44s

$ # Get found offset from the logs
$ kubectl logs jobs/ova
Found lukovitsa... in 23m14s after 1003371311076 attempts (719798516 attempts/s)
---
hostname: lukovitsa6jy7sldxvdw7wwzdmf5sezbwgr5uf57kkhi3jep25g2d2id.onion
offset: sgowAsMLwBk=

$ # Locally generate vanity keypair by offsetting the starting secret key
$ echo PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAABgZ5a7kuS0N1jaA12gtsqI87RPS1eqSj4KWpwXukWtV7pFj6gS200J96P8JDWTpvx000KF3r4l+xYcIJszhPZk | onion-vanity-address --offset=sgowAsMLwBk=
---
hostname: lukovitsa6jy7sldxvdw7wwzdmf5sezbwgr5uf57kkhi3jep27gzjlid.onion
hs_ed25519_public_key: PT0gZWQyNTUxOXYxLXB1YmxpYzogdHlwZTAgPT0AAABdFOqicgeTj8ljvUdv2tkbC9kTIbGj2he/Uo6NpI/XzQ==
hs_ed25519_secret_key: PT0gZWQyNTUxOXYxLXNlY3JldDogdHlwZTAgPT0AAAAoaPTTqGQGyF3aA12gtsqI87RPS1eqSj4KWpwXukWtVyHuiixSBYjSDLiBwGmeqebH1FX7vsHRPBrojpTFiCGQ

$ # Delete the job
$ kubectl delete job ova
job.batch "ova" deleted

Similar tools

The fastest search algorithm

Tor Onion Service address is derived from ed25519 public key. The tool generates candidate public keys until it finds one that has a specified prefix when encoded as onion address.

ed25519 keypair consists of:

  • 32-byte secret key (scalar) - a random value that serves as the secret
  • 32-byte public key (point) - derived by scalar multiplication of the base point by the scalar

ed25519 public key is 32-byte y-coordinate of a point on a Twisted Edwards curve equivalent to Curve25519.

Both mkp224o and onion-vanity-address leverage additive properties of elliptic curves to avoid full scalar multiplication for each candidate key. Addition of points requires expensive field inversion operation and both tools utilize batch field inversion (Montgomery trick) to perform single field inversion per batch of candidate points.

The key performance difference is that while mkp224o uses point arithmetic that calculates both coordinates for each candidate point, onion-vanity-address uses curve coordinate symmetry and calculates only y-coordinates to reduce number of field operations.

The algorithm has amortized cost 5M + 2A per candidate key, where M is field multiplication and A is field addition.

See also:

About

Fast Tor Onion Service vanity address generator

Topics

Resources

License

Stars

Watchers

Forks

Packages