Creating a MD5 Hash Dictionary Script

Creating a MD5 Hash Dictionary Script

Play this article

Summary MD5

  • MD5 is a cryptographic hash function, designed to be a one-way function, which means that it is not possible to directly decrypt an MD5 value to get the original input.

  • The MD5 algorithm is no longer considered secure for password encryption as it is vulnerable to collision attacks and other hash-cracking techniques. We recommend using stronger hashing algorithms such as SHA-256 or bcrypt instead. Therefore, it is quite common to find MD5 hash dictionaries on the internet to decrypt.

Introduction

  • To create a password, the algorithm uses 91 characters as follows:
const lowerCaseChars = 'abcdefghijklmnopqrstuvwxyzç';
const upperCaseChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZÇ';
const specialChars = '!@#$%^&*()-_+=<>?/,.:;{}[]|';
const numericChars = '0123456789';
  • Totaling 91 different characters.

  • Let's say I want to make a password with 6 characters with these 91 characters, remembering that characters can be repeated.

  • So, we have exponentiation: 91^6 = 91 x 91 x 91 x 91 x 91 x 91 = 567,869,252,041 (billion) possible password combinations.

Estimating Time

  • Imagine that 1 current CPU of my i5 here can do 100 passwords per second. I did some calculations here:

  • 1 second = 100 passwords

  • 1 minute = 6000 passwords

  • 1 hour = 6000 x 60 = 360,000 passwords

  • 1 day = 24 x 360,000 = 8,640,000 passwords

  • 567,869,252,041 possible password combinations / 8,640,000 passwords per day = ~65725 days

  • 65725 days / 365 days = it would take on average ~180 years to create all possible password combinations of length 6 using those 91 characters!

Algorithm

  • In this algorithm, using parallelism, the algorithm uses the 8 CPUs available in parallel that I have here on my machine.

  • I had each worker create 8 possible password/dictionary combinations:

  • 1 worker makes passwords with 6 characters

  • 1 worker makes passwords with 7 characters

  • Until the last worker, making passwords with 13 characters

  • The 8 workers creating the passwords at the same time, in parallel.

  • Each worker saves the possible combinations in a different JSON format dictionary, both with a plain password along with its MD5 hashed password.

Conclusion

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