Skip to content

Creating a MD5 Hash Dictionary Script

Summary MD5

Introduction

const lowerCaseChars = "abcdefghijklmnopqrstuvwxyzç";
const upperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZÇ";
const specialChars = "!@#$%^&*()-_+=<>?/,.:;{}[]|";
const numericChars = "0123456789";

Estimating Time

Algorithm

Conclusion

Script Example in Javascript

const cluster = require("cluster");
const totalCPUs = require("os").cpus().length;
const fs = require("fs");
const crypto = require("crypto");

const dictionaryMD5Passwords = {
  6: [],
  7: [],
  8: [],
  9: [],
  10: [],
  11: [],
  12: [],
  13: [],
};

const indexes = [0, 1, 2, 3, 4, 5, 6, 7]; // each worker index
const lowerCaseChars = "abcdefghijklmnopqrstuvwxyzç";
const upperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZÇ";
const specialChars = "!@#$%^&*()-_+=<>?/,.:;{}[]|";
const numericChars = "0123456789";

const allPasswordPossibleCharacters =
  lowerCaseChars + upperCaseChars + specialChars + numericChars;

function generateCombinationsWithRepetition(inputString, combinationLength) {
  function generateHelper(currentPassword) {
    if (currentPassword.length === combinationLength) {
      const password = {
        plainText: currentPassword,
        md5: crypto.createHash("md5").update(currentPassword).digest("hex"),
      };

      console.log(password);

      dictionaryMD5Passwords[combinationLength].push(password);

      fs.writeFileSync(
        `./md5_hash_dictionary/passwords_length_${combinationLength}.json`,
        JSON.stringify(dictionaryMD5Passwords[combinationLength], null, 4),
        "utf8"
      );

      return;
    }

    for (let i = 0; i < inputString.length; i++) {
      const char = inputString[i];
      const newCombination = currentPassword + char;
      generateHelper(newCombination);
    }
  }

  generateHelper("");
}

if (cluster.isMaster) {
  for (let i = 0; i < totalCPUs; i++) {
    const worker = cluster.fork();
    worker.on("message", message => {
      console.log(
        `\nWORKER ID ${worker.process.pid} => received message: ${message}\n`
      );
    });
  }

  let workerIndex = 0;

  for (const index of indexes) {
    const worker = Object.values(cluster.workers)[workerIndex];
    if (worker) {
      let combinationLength = index + 6;
      worker.send(combinationLength);
      workerIndex = (workerIndex + 1) % totalCPUs;
    }
  }

  cluster.on("exit", worker => {
    console.log(`Worker ${worker.process.pid} finished his job!`);
  });
} else {
  process.on("message", async combinationLength => {
    generateCombinationsWithRepetition(
      allPasswordPossibleCharacters,
      combinationLength
    );
  });
}

Script Example in Go

package main

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"sync"
	"time"
)

var allPasswordPossibleCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+=<>?/,.:;{}[]|"

type Password struct {
	PlainText string `json:"plainText"`
	MD5       string `json:"md5"`
}

func generateCombinationsWithRepetition(length int, workerID int, wg *sync.WaitGroup) {
	defer wg.Done()

	start := time.Now()

	var passwords []Password
	totalRequestsMade := 0

	var generateHelper func(currentPassword string)

	generateHelper = func(currentPassword string) {
		if len(currentPassword) == length {
			md5Hash := md5.New()
			md5Hash.Write([]byte(currentPassword))
			md5String := fmt.Sprintf("%x", md5Hash.Sum(nil))

			passwords = append(passwords, Password{
				PlainText: currentPassword,
				MD5:       md5String,
			})

			totalRequestsMade++
			fmt.Printf("Worker %d generated: {\"plainText\": \"%s\", \"md5\": \"%s\"}\n", workerID, currentPassword, md5String)
			return
		}

		for _, char := range allPasswordPossibleCharacters {
			generateHelper(currentPassword + string(char))
			// time.Sleep(1 * time.Second) // Uncomment to create 1 password per second
		}
	}

	generateHelper("")

	duration := time.Since(start)
	fmt.Printf("Worker %d sent all passwords in %v\n", workerID, duration)
	fmt.Printf("Worker %d generated %d passwords\n", workerID, totalRequestsMade)

	dir := "./dictionary-golang"
	if err := os.MkdirAll(dir, 0755); err != nil {
		fmt.Printf("Error creating directory: %v\n", err)
		return
	}

	filePath := filepath.Join(dir, fmt.Sprintf("passwords_length_%d.json", length))
	file, err := os.Create(filePath)
	if err != nil {
		fmt.Printf("Error creating file %s: %v\n", filePath, err)
		return
	}
	defer file.Close()

	encoder := json.NewEncoder(file)
	encoder.SetIndent("", "  ")
	if err := encoder.Encode(passwords); err != nil {
		fmt.Printf("Error encoding JSON to file %s: %v\n", filePath, err)
		return
	}

	fmt.Printf("Worker %d saved passwords to %s\n", workerID, filePath)
}

func main() {
	numWorkers := runtime.NumCPU()
	var wg sync.WaitGroup

	fmt.Printf("Master setting up %d workers...\n", numWorkers)

	for i := 0; i < numWorkers; i++ {
		wg.Add(1)
		go func(workerID int) {
			defer wg.Done()
			length := 6 + workerID
			fmt.Printf("Worker %d processing length %d\n", workerID, length)
			generateCombinationsWithRepetition(length, workerID, &wg)
		}(i)
	}

	wg.Wait()
}