From e8070b0c8604f4b8710ea01be9b0761a66c7343c Mon Sep 17 00:00:00 2001 From: milahu Date: Tue, 31 Aug 2021 21:21:40 +0200 Subject: [PATCH] pass regex by argv --- main.go | 101 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 26 deletions(-) diff --git a/main.go b/main.go index ccfa8a4..4984431 100644 --- a/main.go +++ b/main.go @@ -3,51 +3,84 @@ package main import ( "crypto/rand" "fmt" - "io/ioutil" + //"io/ioutil" "log" "os" "regexp" "runtime" - "strings" + //"strings" + "encoding/base64" "github.com/libp2p/go-libp2p-core/crypto" "github.com/libp2p/go-libp2p-core/peer" ) var ( - alphabet = regexp.MustCompile("^[123456789abcdefghijklmnopqrstuvwxyz]+$") numWorkers = runtime.NumCPU() ) // Key stores PrettyID containing desired substring at Index type Key struct { PrettyID string - Index int + Index int + Part string + PrivateKey string } func main() { if len(os.Args) != 2 { fmt.Printf(` -This tool generates IPFS public and private keypair until it finds public key -which contains required substring. Keys are stored in local directory. If you -like one of them, you can move it to ~/.ipfs/keystore/ to use it with IPFS. +This tool can generate IPFS public and private keypairs +and filter the public keys by regex, to find vanity IPFS public keys + +Keypairs are printed to stdout and to output.txt + +To use a key, edit your ~/.ipfs/config file, which is generated by ipfs init +Identity.PeerID is your public key +Identity.PrivKey is your private key in base64 encoding Usage: - %s {part} - For fast results suggested length of public key part is 4-5 characters + %s {regex} + For fast results, use a short substring of 4-5 characters + +Alphabet of public key: + [1-9a-zA-Z] + +Regex samples: + hello$ + (?i)hello + (foo|bar)$ + +Regex basics: + (?i) add this prefix to make the regex case-insensitive + (a|b) a or b + $ end of string + ^ start of string. not needed here, the start is mostly constant + +Regex docs: + https://duckduckgo.com/?q=golang+regexp + https://yourbasic.org/golang/regexp-cheat-sheet/ + https://golangdocs.com/regex-in-golang-regexp-package + `, os.Args[0]) os.Exit(1) } - part := strings.ToLower(os.Args[1]) - if !alphabet.MatchString(part) { - fmt.Println("{part} must match the alphabet:", alphabet.String()) - os.Exit(2) + + partRegex := regexp.MustCompile(os.Args[1]) + // TODO? validate regex with alphabet + //alphabet = regexp.MustCompile("^[123456789abcdefghijklmnopqrstuvwxyz]+$") + + outputFile, err := os.OpenFile("output.txt", os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0644) + if err != nil { + log.Println(err) } + defer outputFile.Close() + runtime.GOMAXPROCS(numWorkers) keyChan := make(chan Key) for i := 0; i < numWorkers; i++ { go func() { - err := generateKey(part, keyChan) + err := generateKey(partRegex, keyChan) if err != nil { log.Fatal(err) } @@ -55,15 +88,27 @@ Usage: } for key := range keyChan { fmt.Printf( - "%s\u001b[32m%s\u001b[0m%s\n", + // TODO allow to disable color + "%s %s\u001b[32m%s\u001b[0m%s %s\n", + //"%s %s%s%s %s\n", + key.Part, key.PrettyID[:key.Index], - key.PrettyID[key.Index:len(part)+key.Index], - key.PrettyID[len(part)+key.Index:]) + key.PrettyID[key.Index:len(key.Part)+key.Index], + key.PrettyID[len(key.Part)+key.Index:], + key.PrivateKey, + ) + // TODO allow to disable + _, err := outputFile.WriteString( + fmt.Sprintf("%s %s %s\n", key.Part, key.PrettyID, key.PrivateKey), + ) + if err != nil { + log.Println(err) + } } } -func generateKey(part string, keyChan chan Key) error { +func generateKey(partRegex *regexp.Regexp, keyChan chan Key) error { for { privateKey, publicKey, err := crypto.GenerateEd25519Key(rand.Reader) if err != nil { @@ -74,23 +119,27 @@ func generateKey(part string, keyChan chan Key) error { return err } prettyID := peerID.Pretty() - lowerID := strings.ToLower(prettyID) - idx := strings.Index(lowerID, part) - if idx == -1 { + + if !partRegex.MatchString(prettyID) { continue } + + part := partRegex.FindString(prettyID) + idx := partRegex.FindStringIndex(prettyID)[0] + privateKeyBytes, err := privateKey.Raw() if err != nil { return err } - err = ioutil.WriteFile(prettyID, privateKeyBytes, 0600) - // TODO print privateKey in base64, as in ~/.ipfs/config .Identity.PrivKey - if err != nil { - return err - } + + privateKey64 := make([]byte, base64.StdEncoding.EncodedLen(len(privateKeyBytes))) + base64.StdEncoding.Encode(privateKey64, privateKeyBytes) + keyChan <- Key{ PrettyID: prettyID, Index: idx, + Part: part, + PrivateKey: string(privateKey64), } } }