From 797f70835d4991ac2f481c8d56017a9068ea71e9 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 25 Jun 2022 22:20:54 +0300 Subject: [PATCH 1/6] Update dependencies and Go version --- go.mod | 6 +++--- go.sum | 14 ++++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index bbf433b..239e351 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/rdkr/oniongen-go -go 1.14 +go 1.18 require ( - golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad - golang.org/x/sys v0.0.0-20201223074533-0d417f636930 // indirect + golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d + golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect ) diff --git a/go.sum b/go.sum index 38d4202..51dd7f1 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,4 @@ -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo= -golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810 h1:rHZQSjJdAI4Xf5Qzeh2bBc5YJIkPFVM6oDtMFYmgws0= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 580999e557cea95f53b872979a40fb54dc4740ef Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 25 Jun 2022 22:21:59 +0300 Subject: [PATCH 2/6] README.md imporve --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2119030..fae5bce 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,17 @@ v3 .onion address vanity URL generator written in Go. -This implementation generates random ed25519 keys across all CPU cores. The ed25519 public key is converted to a Tor v3 .onion address which is then compared to a user supplied regex to find a vanity URL. If the regex for the .onion address matches, the secret key is expanded for use by Tor and the public key, secret key, and hostname are written to file in a new directory named for the .onion address. The program terminates when the user supplied number of addresses have been generated. +This implementation generates random ed25519 keys across all CPU cores. +The ed25519 public key is converted to a Tor v3 .onion address which is then compared to a user supplied regex to find a vanity URL. +If the regex for the .onion address matches, the secret key is expanded for use by Tor and the public key, secret key, and hostname are written to file in a new directory named for the .onion address. +The program terminates when the user supplied number of addresses have been generated. ## Usage ``` go run main.go - regex regex pattern addresses should match, consisiting of: A-Z, 2-7 + regex regex pattern addresses should match, consisiting of: a-z, 2-7 number number of matching addresses to generate before exiting ``` @@ -22,7 +25,7 @@ go run main.go "^test" 5 ``` ## References - +- Onion Addresses are defined in [Tor Rendezvous Specification - Version 3](https://github.com/torproject/torspec/blob/main/rend-spec-v3.txt) - public key -> onion: https://github.com/torproject/torspec/blob/12271f0e6db00dee9600425b2de063e02f19c1ee/rend-spec-v3.txt#L2136-L2158 - secret key expansion: - implementation in mkp224o: https://github.com/cathugger/mkp224o/blob/af5a7cfe122ba62e819b92c8b5a662151a284c69/ed25519/ed25519.h#L153-L161 From 0c22254f1a29fbd1935c35ea697fbe7fc51325b7 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 25 Jun 2022 22:33:20 +0300 Subject: [PATCH 3/6] Cleanup --- main.go | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/main.go b/main.go index 67bc44d..64a6276 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ import ( "crypto/sha512" "encoding/base32" "fmt" - "io/ioutil" "os" "regexp" "runtime" @@ -18,9 +17,7 @@ import ( ) func generate(wg *sync.WaitGroup, re *regexp.Regexp) { - for { - publicKey, secretKey, err := ed25519.GenerateKey(nil) checkErr(err) @@ -36,45 +33,42 @@ func generate(wg *sync.WaitGroup, re *regexp.Regexp) { } func expandSecretKey(secretKey ed25519.PrivateKey) [64]byte { - hash := sha512.Sum512(secretKey[:32]) + // clamp the blinding factor 'h' according to the ed25519 spec hash[0] &= 248 hash[31] &= 127 hash[31] |= 64 return hash - } func encodePublicKey(publicKey ed25519.PublicKey) string { - // checksum = H(".onion checksum" || pubkey || version) var checksumBytes bytes.Buffer checksumBytes.Write([]byte(".onion checksum")) - checksumBytes.Write([]byte(publicKey)) + checksumBytes.Write(publicKey) checksumBytes.Write([]byte{0x03}) checksum := sha3.Sum256(checksumBytes.Bytes()) // onion_address = base32(pubkey || checksum || version) var onionAddressBytes bytes.Buffer - onionAddressBytes.Write([]byte(publicKey)) - onionAddressBytes.Write([]byte(checksum[:2])) + onionAddressBytes.Write(publicKey) + onionAddressBytes.Write(checksum[:2]) onionAddressBytes.Write([]byte{0x03}) onionAddress := base32.StdEncoding.EncodeToString(onionAddressBytes.Bytes()) return strings.ToLower(onionAddress) - } func save(onionAddress string, publicKey ed25519.PublicKey, secretKey [64]byte) { - os.MkdirAll(onionAddress, 0700) + checkErr(os.MkdirAll(onionAddress, 0700)) secretKeyFile := append([]byte("== ed25519v1-secret: type0 ==\x00\x00\x00"), secretKey[:]...) - checkErr(ioutil.WriteFile(onionAddress+"/hs_ed25519_secret_key", secretKeyFile, 0600)) + checkErr(os.WriteFile(onionAddress+"/hs_ed25519_secret_key", secretKeyFile, 0600)) publicKeyFile := append([]byte("== ed25519v1-public: type0 ==\x00\x00\x00"), publicKey...) - checkErr(ioutil.WriteFile(onionAddress+"/hs_ed25519_public_key", publicKeyFile, 0600)) + checkErr(os.WriteFile(onionAddress+"/hs_ed25519_public_key", publicKeyFile, 0600)) - checkErr(ioutil.WriteFile(onionAddress+"/hostname", []byte(onionAddress+".onion\n"), 0600)) + checkErr(os.WriteFile(onionAddress+"/hostname", []byte(onionAddress+".onion\n"), 0600)) } func checkErr(err error) { @@ -84,14 +78,13 @@ func checkErr(err error) { } func main() { - // Set runtime to use all available CPUs. runtime.GOMAXPROCS(runtime.NumCPU()) // Compile regex from first argument. re, _ := regexp.Compile(os.Args[1]) - // Get the number of desired addreses from second argument. + // Get the number of desired addresses from second argument. numAddresses, _ := strconv.Atoi(os.Args[2]) // WaitGroup of size equal to desired number of addresses @@ -105,5 +98,4 @@ func main() { // Exit after the desired number of addresses have been found. wg.Wait() - } From 6490459cda5adbdb380055490fcb76171d6c8483 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 25 Jun 2022 22:37:38 +0300 Subject: [PATCH 4/6] base32 Encoding to lower case --- main.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 64a6276..f744998 100644 --- a/main.go +++ b/main.go @@ -10,12 +10,15 @@ import ( "regexp" "runtime" "strconv" - "strings" "sync" "golang.org/x/crypto/sha3" ) +const b32Lower = "abcdefghijklmnopqrstuvwxyz234567" + +var b32Enc = base32.NewEncoding(b32Lower).WithPadding(base32.NoPadding) + func generate(wg *sync.WaitGroup, re *regexp.Regexp) { for { publicKey, secretKey, err := ed25519.GenerateKey(nil) @@ -54,9 +57,9 @@ func encodePublicKey(publicKey ed25519.PublicKey) string { onionAddressBytes.Write(publicKey) onionAddressBytes.Write(checksum[:2]) onionAddressBytes.Write([]byte{0x03}) - onionAddress := base32.StdEncoding.EncodeToString(onionAddressBytes.Bytes()) + onionAddress := b32Enc.EncodeToString(onionAddressBytes.Bytes()) - return strings.ToLower(onionAddress) + return onionAddress } func save(onionAddress string, publicKey ed25519.PublicKey, secretKey [64]byte) { @@ -81,8 +84,9 @@ func main() { // Set runtime to use all available CPUs. runtime.GOMAXPROCS(runtime.NumCPU()) + prefix := os.Args[1] // Compile regex from first argument. - re, _ := regexp.Compile(os.Args[1]) + re, _ := regexp.Compile(prefix) // Get the number of desired addresses from second argument. numAddresses, _ := strconv.Atoi(os.Args[2]) From 6d78363dda18f3949bbec218276aca0580f7c2e0 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sat, 25 Jun 2022 22:39:20 +0300 Subject: [PATCH 5/6] Make: build with GOAMD64=v3 optimization The make.sh can be called from Windows --- .gitignore | 1 + Makefile | 4 ++++ make.sh | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 Makefile create mode 100644 make.sh diff --git a/.gitignore b/.gitignore index 7fd015b..2d1fa53 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +oniongen # Created by https://www.gitignore.io/api/go # Edit at https://www.gitignore.io/?templates=go diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cc4871f --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +build: + ./make.sh build +update_libs: + ./make.sh update_libs diff --git a/make.sh b/make.sh new file mode 100644 index 0000000..071d321 --- /dev/null +++ b/make.sh @@ -0,0 +1,32 @@ +build() { + go mod download + GOAMD64=v3 go build -tags release -o ./oniongen +} + +update_libs() { + go get -u + go mod tidy +} + +help() { + go get -u + echo "build update_libs" +} + +progname=$(basename $0) +subcommand=$1 +case $subcommand in + "" | "-h" | "--help") + help + ;; + *) + shift + echo "Executing: $subcommand" + ${subcommand} "$@" + if [ $? = 127 ]; then + echo "Error: '$subcommand' is not a known subcommand." >&2 + help + exit 1 + fi + ;; +esac From f3c379720211b1526cc970bdc41f2bbf303ee1af Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Thu, 19 Oct 2023 23:29:01 +0300 Subject: [PATCH 6/6] README.md key expansion --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fae5bce..372a2e6 100644 --- a/README.md +++ b/README.md @@ -28,5 +28,7 @@ go run main.go "^test" 5 - Onion Addresses are defined in [Tor Rendezvous Specification - Version 3](https://github.com/torproject/torspec/blob/main/rend-spec-v3.txt) - public key -> onion: https://github.com/torproject/torspec/blob/12271f0e6db00dee9600425b2de063e02f19c1ee/rend-spec-v3.txt#L2136-L2158 - secret key expansion: - - implementation in mkp224o: https://github.com/cathugger/mkp224o/blob/af5a7cfe122ba62e819b92c8b5a662151a284c69/ed25519/ed25519.h#L153-L161 - - possibly related: https://github.com/torproject/torspec/blob/12271f0e6db00dee9600425b2de063e02f19c1ee/rend-spec-v3.txt#L2268-L2327 ?? + - [specification](https://github.com/torproject/torspec/blob/12271f0e6db00dee9600425b2de063e02f19c1ee/rend-spec-v3.txt#L2268-L2327) + - [should the secret key be expanded?](https://tor.stackexchange.com/questions/23849/tor-onion-domain-should-the-secret-key-be-expanded) + - [implementation in tor](https://gitlab.torproject.org/tpo/core/tor/-/blob/main/src/ext/ed25519/donna/ed25519_tor.c#L65) + - [implementation in mkp224o](https://github.com/cathugger/mkp224o/blob/af5a7cfe122ba62e819b92c8b5a662151a284c69/ed25519/ed25519.h#L153-L161)