Creating a MD5 Hash Dictionary Script

Aug 15, 2023·

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.

• 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

• I made this algorithm for didactic purposes, and out of pure curiosity/technical interest.

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

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) {

}

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) => {