Skip to content

Instantly share code, notes, and snippets.

@wybiral
Last active July 3, 2022 18:44
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wybiral/8f737644fc140c97b6b26c13b1409837 to your computer and use it in GitHub Desktop.
Save wybiral/8f737644fc140c97b6b26c13b1409837 to your computer and use it in GitHub Desktop.
Example of generating Tor onions using the new ED25519-v3 format
// Example of generating Tor onion using the new ED25519-v3 format
package main
import (
"crypto/rand"
"crypto/sha512"
"encoding/base32"
"encoding/base64"
"fmt"
"golang.org/x/crypto/ed25519"
"golang.org/x/crypto/sha3"
"log"
"strings"
)
// Hidden service version
const version = byte(0x03)
// Salt used to create checkdigits
const salt = ".onion checksum"
func main() {
pub, pri, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Fatal(err)
}
fmt.Println("Address:", getServiceID(pub)+".onion")
fmt.Println("Private Key:", expandKey(pri))
}
// Expand ed25519.PrivateKey to (a || RH) form, return base64
func expandKey(pri ed25519.PrivateKey) string {
h := sha512.Sum512(pri[:32])
// Set bits so that h[:32] is private scalar "a"
h[0] &= 248
h[31] &= 127
h[31] |= 64
// Since h[32:] is RH, h is now (a || RH)
return base64.StdEncoding.EncodeToString(h[:])
}
func getCheckdigits(pub ed25519.PublicKey) []byte {
// Calculate checksum sha3(".onion checksum" || publicKey || version)
checkstr := []byte(salt)
checkstr = append(checkstr, pub...)
checkstr = append(checkstr, version)
checksum := sha3.Sum256(checkstr)
return checksum[:2]
}
func getServiceID(pub ed25519.PublicKey) string {
// Construct onion address base32(publicKey || checkdigits || version)
checkdigits := getCheckdigits(pub)
combined := pub[:]
combined = append(combined, checkdigits...)
combined = append(combined, version)
serviceID := base32.StdEncoding.EncodeToString(combined)
return strings.ToLower(serviceID)
}
@ageis
Copy link

ageis commented Apr 17, 2021

Does this accept existing public v3 .onion address as $ARGV[1] or something, or do I need to hack it? apologies, haven't written much Go lately.

@stokito
Copy link

stokito commented Jul 3, 2022

@ageis it's just generates an onion domain and it's private key. But the public key is not stored.

You can try my version vanity onion generator https://github.com/stokito/oniongen-go/tree/optimization (note the branch is optimization )

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