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()
}