Skip to content

Instantly share code, notes, and snippets.

@nektro
Last active July 5, 2024 18:32
Show Gist options
  • Save nektro/f84a660caf4a9db874417967fcecf8d2 to your computer and use it in GitHub Desktop.
Save nektro/f84a660caf4a9db874417967fcecf8d2 to your computer and use it in GitHub Desktop.
Golang Vanity v3 Onion Address Generator
package main
import (
"crypto"
"crypto/ed25519"
"encoding/base32"
"encoding/base64"
"encoding/hex"
"flag"
"fmt"
"log"
"os"
"strings"
_ "golang.org/x/crypto/sha3"
)
// v3 Onion Address Generator
//
// Do `go build && ./onion-address-gen` and run with the `-prefix` flag to search.
// this will generate hostnames, as well as the necessary public and secret keys
// needed to be able to validate you own the address. matching hostnames will be
// written to `./addresses.txt`.
//
// `./addresses.txt` Format
// const l = line.split(' ')
// l[0]: the index at which this name was found during the run
// l[1]: the onion address
// l[2]: the public key, base64 encoded
// l[3]: the secret key, base64 decoded
//
// in order to use these contents, create a directory. eg: `./tor_site`
// echo "l[1]" | tee ./hostname
// echo "l[2]" | base64 -d | tee ./hs_ed25519_public_key
// echo "l[3]" | base64 -d | tee ./hs_ed25519_secret_key
//
// std-lib required to implement this in another language
// os.Create: File
// fmt.Fprintln
// String.HasPrefix
// fmt.Println
// ed25519.GenerateKey
// crypto.SHA3_256.New
// hex.Encode
// base32.Encode
// base64.Encode
func main() {
prefix := flag.String("prefix", "", "Prefix for the vanity hostname you wish to discover")
flag.Parse()
f, _ := os.OpenFile("./addresses.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, os.ModePerm)
n := 0
for true {
n++
adr, pb, pv := newAddress()
if strings.HasPrefix(adr, *prefix) {
fmt.Fprintln(f, n, adr, doBase64(pb), doBase64(pv))
log.Println(n, adr)
}
}
}
func newAddress() (string, string, string) {
pub, prv, _ := ed25519.GenerateKey(nil)
version := "\x03"
key := string(pub)
checksum := h(".onion checksum" + key + version)[:2]
addr := doBase32(key + checksum + version)
keyPub := "== ed25519v1-public: type0 ==" + "\x00\x00\x00" + string(pub)
keyPrv := "== ed25519v1-secret: type0 ==" + "\x00\x00\x00" + string(prv)
return addr + ".onion", keyPub, keyPrv
}
func h(d string) string {
a := crypto.SHA3_256.New()
a.Write([]byte(d))
b := hex.EncodeToString(a.Sum([]byte{}))
return b
}
func doBase32(d string) string {
return strings.ToLower(base32.StdEncoding.EncodeToString([]byte(d)))
}
func doBase64(d string) string {
return base64.StdEncoding.EncodeToString([]byte(d))
}
@stokito
Copy link

stokito commented Jun 25, 2022

Also it looks like you are missing one thing
https://github.com/rdkr/oniongen-go/blob/master/main.go#L38=

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment