Last active
January 21, 2024 07:43
-
-
Save jonnadul/ad4eab0bac13cf44cb42e401045e1dac to your computer and use it in GitHub Desktop.
Simple go-lang app for brute forcing the dictionary phrase behind SHA1 seed values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ecdsaseedbf | |
import ( | |
"context" | |
"crypto/sha1" | |
"encoding/hex" | |
"fmt" | |
"strings" | |
"sync" | |
"time" | |
"unicode" | |
openai "github.com/sashabaranov/go-openai" | |
) | |
const maxOpenAICalls = 5 | |
const maxPostPendLen = 3 | |
const sleepDuration = 5 * time.Second | |
type FoundSeed struct { | |
seedName string | |
seed string | |
found bool | |
phrase string | |
} | |
var foundSeedsMutex sync.Mutex | |
var foundSeeds []FoundSeed | |
/* | |
* Each phrase from OpenAI is a numbered item, need to truncate that | |
* leading digit + '.' + ' ' to get the raw sentence back. | |
*/ | |
func truncLeadingNumber(preTrunc string) string { | |
truncStr := preTrunc | |
done := false | |
for !done { | |
if len(truncStr) <= 0 { | |
done = true | |
} else { | |
if len(truncStr) > 0 && | |
(unicode.IsDigit(rune(truncStr[0])) || truncStr[0] == '.' || truncStr[0] == ' ') { | |
truncStr = truncStr[1:] | |
} else { | |
done = true | |
} | |
} | |
} | |
return truncStr | |
} | |
func hexsha1(input string) string { | |
h := sha1.New() | |
h.Write([]byte(input)) | |
return strings.ToUpper(hex.EncodeToString(h.Sum(nil))) | |
} | |
func generatePerms(basePhrase string, index int, length int, current string) { | |
if index == length { | |
fullPhrases := []string{ | |
basePhrase + current, | |
current + basePhrase, | |
current + basePhrase + current, | |
} | |
results := []string{ | |
hexsha1(basePhrase + current), | |
hexsha1(current + basePhrase), | |
hexsha1(current + basePhrase + current), | |
} | |
for idx, result := range results { | |
foundSeedsMutex.Lock() | |
for _, foundSeed := range foundSeeds { | |
if (!foundSeed.found) && (foundSeed.seed == result) { | |
fmt.Printf("Found phase for %s! %s\n", foundSeed.seedName, fullPhrases[idx]) | |
foundSeed.found = true | |
foundSeed.phrase = fullPhrases[idx] | |
} | |
} | |
foundSeedsMutex.Unlock() | |
} | |
return | |
} | |
for i := 0; i < 256; i++ { | |
generatePerms(basePhrase, index+1, length, current+string(rune(i))) | |
} | |
} | |
func main() { | |
foundSeeds = []FoundSeed{ | |
{ | |
seedName: "p_192", | |
seed: "3045AE6FC8422F64ED579528D38120EAE12196D5", | |
found: false, | |
phrase: "", | |
}, | |
{ | |
seedName: "p_224", | |
seed: "BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5", | |
found: false, | |
phrase: "", | |
}, | |
{ | |
seedName: "p_256", | |
seed: "C49D360886E704936A6678E1139D26B7819F7E90", | |
found: false, | |
phrase: "", | |
}, | |
{ | |
seedName: "p_384", | |
seed: "A335926AA319A27A1D00896A6773A4827ACDAC73", | |
found: false, | |
phrase: "", | |
}, | |
{ | |
seedName: "p_521", | |
seed: "D09E8800291CB85396CC6717393284AAA0DA64BA", | |
found: false, | |
phrase: "", | |
}, | |
} | |
client := openai.NewClient("<OpenAI Token>") | |
messages := []openai.ChatCompletionMessage{ | |
{ | |
Role: openai.ChatMessageRoleSystem, | |
Content: "Return a list of 100 similar phrases.", | |
}, | |
{ | |
Role: openai.ChatMessageRoleUser, | |
Content: "Jerry and Bob need raises", | |
}, | |
} | |
var wg sync.WaitGroup | |
for k := 0; k < maxOpenAICalls; k++ { | |
fmt.Println("Calling OpenAI for list of 100 phrases.") | |
resp, err := client.CreateChatCompletion( | |
context.Background(), | |
openai.ChatCompletionRequest{ | |
Model: openai.GPT3Dot5Turbo, | |
Messages: messages, | |
}, | |
) | |
if err != nil { | |
fmt.Println("Error encountered in call to OpenAI") | |
break | |
} | |
listOfPhrases := strings.Split(resp.Choices[0].Message.Content, "\n") | |
for _, phrase := range listOfPhrases { | |
basePhrase := strings.Trim(truncLeadingNumber(phrase), ".") | |
for ppLen := 0; ppLen <= maxPostPendLen; ppLen++ { | |
fmt.Printf("Starting for phrase %s and postpend length %d\n", basePhrase, ppLen) | |
wg.Add(1) | |
go func(bP string, pL int) { | |
generatePerms(bP, 0, pL, "") | |
fmt.Printf("Complete for phrase %s and postpend length %d\n", bP, pL) | |
wg.Done() | |
}(basePhrase, ppLen) | |
} | |
time.Sleep(sleepDuration) | |
} | |
messages = append(messages, openai.ChatCompletionMessage{ | |
Role: openai.ChatMessageRoleAssistant, | |
Content: resp.Choices[0].Message.Content, | |
}) | |
messages = append(messages, openai.ChatCompletionMessage{ | |
Role: openai.ChatMessageRoleUser, | |
Content: "Can you share the next 100?", | |
}) | |
} | |
fmt.Println("Waiting...") | |
wg.Wait() | |
foundSeedsMutex.Lock() | |
for _, foundSeed := range foundSeeds { | |
fmt.Printf("seedName = %s, seed = %s, found = %b, phrase = %s\n", | |
foundSeed.seedName, | |
foundSeed.seed, | |
foundSeed.found, | |
foundSeed.phrase) | |
} | |
foundSeedsMutex.Unlock() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment