diff --git a/password/password.go b/password/password.go index 3b4fb85..883c7a3 100644 --- a/password/password.go +++ b/password/password.go @@ -47,7 +47,7 @@ func Check(input string, wordList, passwordList []string) (string, error) { // Check if password is in common passwords for _, entry := range passwordList { - if strings.Contains(strings.ToLower(entry), strings.ToLower(input)) { + if strings.Contains(strings.ToLower(entry), strings.ToLower(input)) && len(entry) > 3 { return "Weak password", fmt.Errorf("password found inside common passwords") } } diff --git a/web/fetcher.go b/web/fetcher.go index b67b1bb..212f86b 100644 --- a/web/fetcher.go +++ b/web/fetcher.go @@ -5,44 +5,110 @@ import ( "io" "net/http" "strings" + "sync" ) +// Response is a model for fetching wordlist +type Response struct { + data string + error error +} + // FetchCommonWords fetches 10,000 common words from a wordlist func FetchCommonWords() ([]string, error) { - // Create a GET request to Github wordlist - resp, err := http.Get("https://raw.githubusercontent.com/first20hours/google-10000-english/refs/heads/master/google-10000-english-no-swears.txt") - if err != nil { - return nil, fmt.Errorf("failed to fetch URL: %v", err) - } - // Close body at end to avoid memory leaks - defer resp.Body.Close() + // Create a waitgroup + var wg sync.WaitGroup - // Read response and parse into string - bytes, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("error reading response body: %v", err) + // Create channels + responses := make(chan Response, 1) + + wg.Add(1) // Start a wait group + wg.Go(func() { + defer wg.Done() + + // Fetch list from github + resp, err := http.Get("https://raw.githubusercontent.com/first20hours/google-10000-english/refs/heads/master/google-10000-english-no-swears.txt") + if err != nil { + responses <- Response{error: fmt.Errorf("failed to fetch URL: %v", err)} + } + + // Defer body close to avoid memory leaks + defer resp.Body.Close() + + // Read response body + bytes, err := io.ReadAll(resp.Body) + if err != nil { + responses <- Response{error: fmt.Errorf("error reading response body: %v", err)} + } + + // Send data to channel + responses <- Response{data: string(bytes), error: nil} + }) + + // Wait for response to finish + go func() { + fmt.Println("Downloading wordlist...") + wg.Wait() + close(responses) + }() + + var wordList []string + + for response := range responses { + if response.error != nil { + return nil, response.error + } + wordList = strings.Split(response.data, "\n") } - // Split response into list - wordList := strings.Split(string(bytes), "\n") return wordList, nil + } // FetchCommonPasswords fetches commonly used passwords from Github func FetchCommonPasswords() ([]string, error) { - // Create GET request to Github for common password list - resp, err := http.Get("https://raw.githubusercontent.com/AnandJogawade/Top-common-passwords/refs/heads/main/Top-common-passwords.v1.txt") - if err != nil { - return nil, fmt.Errorf("failed to fetch password list from Github: %v", err) + var wg sync.WaitGroup // Wait group + + // Create channel + responses := make(chan Response, 1) + + // Start waitgroup + wg.Add(1) + wg.Go(func() { + defer wg.Done() + + // Fetch list from github + resp, err := http.Get("https://raw.githubusercontent.com/AnandJogawade/Top-common-passwords/refs/heads/main/Top-common-passwords.v1.txt") + if err != nil { + responses <- Response{error: fmt.Errorf("failed to fetch password list from github: %v", err)} + } + defer resp.Body.Close() + + // Parse response into string + bytes, err := io.ReadAll(resp.Body) + if err != nil { + responses <- Response{error: fmt.Errorf("failed to parse response body: %v", err)} + } + + responses <- Response{data: string(bytes), error: nil} + }) + + // Wait for request to finish + go func() { + fmt.Println("Downloading password list...") + wg.Wait() + close(responses) + }() + + var passwordList []string + + // Parse response into list + for response := range responses { + if response.error != nil { + return nil, response.error + } + passwordList = strings.Split(response.data, "\n") } - // Parse response into string - bytes, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("failed to parse response body") - } - - // Split bytes into list - passwordList := strings.Split(string(bytes), "\n") return passwordList, nil }