package main import ( "bufio" "crypto/rand" libpeer "cwtch.im/cwtch/peer" "fmt" "git.openprivacy.ca/openprivacy/libricochet-go/utils" "github.com/sethvargo/go-diceware/diceware" "golang.org/x/crypto/ed25519" "io/ioutil" "log" "os" "strconv" "strings" "time" ) func convertCwtchFile(filename string, password string) { peer, err := libpeer.LoadCwtchPeer(filename, password) if err != nil { log.Fatalf("%v", err) } b := []byte("== ed25519v1-secret: type0 ==") b = append(b, peer.GetProfile().Ed25519PrivateKey...) err = ioutil.WriteFile("hs_ed25519_secret_key", b, 0600) if err != nil { log.Fatalf("%v", err) } b = []byte("== ed25519v1-public: type0 ==") b = append(b, peer.GetProfile().Ed25519PublicKey...) err = ioutil.WriteFile("hs_ed25519_public_key", b, 0600) if err != nil { log.Fatalf("%v", err) } b = []byte(peer.GetProfile().Onion + ".onion\n") err = ioutil.WriteFile("hostname", b, 0600) if err != nil { log.Fatalf("%v", err) } fmt.Println("success!") } func convertTorFile(filename string, password string) { log.Fatalf("this code doesn't work and can never work :( it's a math thing") name, _ := diceware.Generate(2) sk, err := ioutil.ReadFile("hs_ed25519_secret_key") if err != nil { log.Fatalf("%v", err) } sk = sk[32:] pk, err := ioutil.ReadFile("hs_ed25519_public_key") if err != nil { log.Fatalf("%v", err) } pk = pk[32:] onion, err := ioutil.ReadFile("hostname") if err != nil { log.Fatalf("%v", err) } onion = onion[:56] peer, err := libpeer.NewCwtchPeer(strings.Join(name, "-"), password, filename) if err != nil { log.Fatalf("%v", err) } fmt.Printf("%d %d %s\n", len(peer.GetProfile().Ed25519PublicKey), len(peer.GetProfile().Ed25519PrivateKey), peer.GetProfile().Onion) peer.GetProfile().Ed25519PrivateKey = sk peer.GetProfile().Ed25519PublicKey = pk peer.GetProfile().Onion = string(onion) peer.Save() log.Printf("success! loaded %d byte pk and %d byte sk for %s.onion\n", len(pk), len(sk), onion) } func vanity() { for { pk, sk, err := ed25519.GenerateKey(rand.Reader) if err != nil { continue } onion := utils.GetTorV3Hostname(pk) for i := 4; i < len(os.Args); i++ { if strings.HasPrefix(onion, os.Args[i]) { peer, err := libpeer.NewCwtchPeer(os.Args[i], os.Args[3], onion+".cwtch") if err != nil { log.Fatalf("%v", err) } peer.GetProfile().Ed25519PrivateKey = sk peer.GetProfile().Ed25519PublicKey = pk peer.GetProfile().Onion = onion peer.Save() log.Printf("found %s.onion\n", onion) } } } } func printHelp() { log.Println("usage: cwtchutil {help, convert-cwtch-file, convert-tor-file, changepw, vanity}") } func main() { if len(os.Args) < 2 { printHelp() os.Exit(1) } switch os.Args[1] { default: printHelp() case "help": printHelp() case "convert-cwtch-file": if len(os.Args) != 4 { log.Println("example: cwtchutil convert-cwtch-file ~/.cwtch/profiles/11ddd78a9918c064e742d5e36a8b8fd4 passw0rd") os.Exit(1) } convertCwtchFile(os.Args[2], os.Args[3]) case "convert-tor-file": if len(os.Args) != 4 { log.Println("example: cwtchutil convert-tor-file /var/lib/tor/hs1 passw0rd") os.Exit(1) } convertTorFile(os.Args[2], os.Args[3]) case "vanity": if len(os.Args) < 5 { log.Println("example: cwtchutil vanity 4 passw0rd erinn openpriv") os.Exit(1) } goroutines, err := strconv.Atoi(os.Args[2]) if err != nil { log.Printf("first parameter after vanity should be a number\n") os.Exit(1) } log.Println("searching. press ctrl+c to stop") for i := 0; i < goroutines; i++ { go vanity() } for { // run until ctrl+c time.Sleep(time.Hour * 24) } case "changepw": if len(os.Args) != 3 { log.Fatalf("example: cwtch changepw ~/.cwtch/profiles/XXX") } fmt.Printf("old password: ") reader := bufio.NewReader(os.Stdin) pw, err := reader.ReadString('\n') if err != nil { log.Fatalf("%v", err) } pw = pw[:len(pw)-1] peer, err := libpeer.LoadCwtchPeer(os.Args[2], pw) if err != nil { log.Fatalf("%v", err) } fmt.Printf("new password: ") newpw1, err := reader.ReadString('\n') if err != nil { log.Fatalf("%v", err) } newpw1 = newpw1[:len(newpw1)-1] // fuck go with this linebreak shit ^ea err = peer.ChangePassword(newpw1) if err != nil { log.Fatalf("%v", err) } log.Println("success!") peer.Save() } }