13 |
14 | ## Features
15 |
16 | - Utilizes goroutines for concurrent password checking to improve performance.
17 | - Supports SHA1 hashing with customizable salt.
18 | - Provides flexibility for using different hashing algorithms.
19 |
20 | ## Usage
21 |
22 | 1. Clone the repository:
23 |
24 | ```bash
25 | git clone https://github.com/IamLucif3r/Go-Hash-Matcher.git
26 | ```
27 |
28 | 2. Navigate to the project directory:
29 |
30 | ```bash
31 | cd Go-Hash-Matcher
32 | ```
33 |
34 | 3. Build the project:
35 |
36 | ```bash
37 | go build main.go
38 | ```
39 |
40 | 4. Run the executable:
41 |
42 | ```bash
43 | ./main
44 | ```
45 |
46 | Replace `main` with the name of the compiled executable if it's different.
47 |
48 | 5. The program will read passwords from the `passwords.txt` file and check for a specific hashed password.
49 |
50 | ## Configuration
51 |
52 | - Adjust the `hashType` variable to use a different hashing algorithm (e.g., SHA256).
53 | - Modify the `salt` variable to change the salt used during hashing.
54 |
55 | ## Dependencies
56 |
57 | The project uses only standard Go libraries and does not require additional dependencies.
58 |
59 | ## Contributing
60 |
61 | Feel free to contribute by opening issues, providing feedback, or submitting pull requests.
62 |
63 |
64 |
--------------------------------------------------------------------------------
/docs/go-hash-matcher-banner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IamLucif3r/Go-Hash-Matcher/ff45e146c42009884b13143703c71281fb5b359e/docs/go-hash-matcher-banner.gif
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/IamLucif3r/Go-Hash-Matcher
2 |
3 | go 1.21.5
4 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "os"
7 | "sync"
8 | "time"
9 |
10 | utils "github.com/IamLucif3r/Go-Hash-Matcher/utils"
11 | )
12 |
13 | var wg sync.WaitGroup
14 |
15 | func checkPassword(value, search, hashType, salt string, results chan bool) {
16 | defer wg.Done()
17 | hashedPassword := utils.CryptBytes(hashType, salt, []byte(value))
18 | if hashedPassword == search {
19 | fmt.Printf("[✅] Hash Matched! Password Found : %s, hash: %s\n", value, hashedPassword)
20 | results <- true
21 | }
22 | }
23 |
24 | func main() {
25 | hashType := "SHA1"
26 | salt := "d"
27 | // Enter Hash you want to decrypt
28 | search := "$SHA1$d$uP0_QaVBpDWFeo8-dRzDqRwXQ2I"
29 | // Provide path for a list of plain text passwords
30 | wordlist := "/usr/share/wordlists/rockyou.txt"
31 |
32 | go utils.ShowLoadingSpinner()
33 |
34 | passwordListFile, err := os.Open(wordlist)
35 | if err != nil {
36 | fmt.Printf("[❗️] Error opening wordlist: %v\n", err)
37 | return
38 | }
39 | defer passwordListFile.Close()
40 |
41 | scanner := bufio.NewScanner(passwordListFile)
42 | results := make(chan bool)
43 |
44 | for scanner.Scan() {
45 | value := scanner.Text()
46 | wg.Add(1)
47 | go checkPassword(value, search, hashType, salt, results)
48 | }
49 |
50 | go func() {
51 | wg.Wait()
52 | close(results)
53 | }()
54 |
55 | select {
56 | case <-results:
57 | case <-time.After(10 * time.Second):
58 | fmt.Println("[❌] Password not found in the given timeout.")
59 | }
60 |
61 | if err := scanner.Err(); err != nil {
62 | fmt.Printf("[❗️] Error reading wordlist: %v\n", err)
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/utils/cryptBytes.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "crypto/rand"
5 | "crypto/sha1"
6 | "encoding/base64"
7 | "fmt"
8 | "strings"
9 | )
10 |
11 | func CryptBytes(hashType, salt string, value []byte) string {
12 | if hashType == "" {
13 | hashType = "SHA1"
14 | }
15 | if salt == "" {
16 | saltBytes := make([]byte, 16)
17 | rand.Read(saltBytes)
18 | salt = base64.URLEncoding.EncodeToString(saltBytes)
19 | }
20 | hash := sha1.New()
21 | hash.Write([]byte(salt))
22 | hash.Write(value)
23 | hashedBytes := hash.Sum(nil)
24 | result := fmt.Sprintf("$%s$%s$%s", hashType, salt, strings.TrimRight(base64.URLEncoding.EncodeToString(hashedBytes), "="))
25 | return result
26 | }
27 |
--------------------------------------------------------------------------------
/utils/getCryptedBytes.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "crypto/sha1"
5 | "encoding/base64"
6 | "strings"
7 | )
8 |
9 | func GetCryptedBytes(hashType, salt string, value []byte) string {
10 | hash := sha1.New()
11 | hash.Write([]byte(salt))
12 | hash.Write(value)
13 | hashedBytes := hash.Sum(nil)
14 | return strings.TrimRight(base64.URLEncoding.EncodeToString(hashedBytes), "=")
15 | }
16 |
--------------------------------------------------------------------------------
/utils/showLoading.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | func ShowLoadingSpinner() {
9 | ticker := time.NewTicker(100 * time.Millisecond)
10 | defer ticker.Stop()
11 |
12 | spinnerFrames := []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
13 |
14 | i := 0
15 | for {
16 | select {
17 | case <-ticker.C:
18 | fmt.Printf("\rChecking passwords %s", spinnerFrames[i])
19 | i = (i + 1) % len(spinnerFrames)
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------