0

In my school's assignment I've been tasked to bruteforce a SHA1 hash in order to find the key.
We're provided with the flag (in SHA1), a password (in SHA1) and they told us that the key was [AAAAAA-ZZZZZZ]. The flag was in the format of SHA1(PASSWORD_KEY).
I was able to get the password via rainbow table method, and now I need to bruteforce the key from AAAAAA-ZZZZZZ. Below is the code that I came up with

function guess(flag, password) {
    for (let char1 = 65; char1 <= 90; char1++) {
        for (let char2 = 65; char2 <= 90; char2++) {
            for (let char3 = 65; char3 <= 90; char3++) {
                for (let char4 = 65; char4 <= 90; char4++) {
                    for (let char5 = 65; char5 <= 90; char5++) {
                        for (let char6 = 65; char6 <= 90; char6++) {
                            const key_guess = String.fromCharCode(char1, char2, char3, char4, char5, char6);
                            const guess = `${password}_${key_guess}`;

                            const shasum = crypto.createHash('sha1');
                            shasum.update(guess);
                            const hashed_guess = shasum.digest('hex');

                            if (hashed_guess === flag) {
                                return key_guess;
                            }
                        }
                    }
                }
            }
        }
    }
}

This works and all but it took my PC ~23s to crack the key. Since I'm writing this in nodejs I thought about utilizing promise wrapping to offload the bruteforce to multiple cores (I'm using a AMD 5600x so there's 6 physical cores) so i came up with this code

async function guessKey(flag, password) {
    return new Promise(async (resolve) => {
        async function guessPromise(startCharAscii, endCharAscii) {
            return new Promise((resolve) => {
                for (let char1 = startCharAscii; char1 <= endCharAscii; char1++) {
                    for (let char2 = 65; char2 <= 90; char2++) {
                        for (let char3 = 65; char3 <= 90; char3++) {
                            for (let char4 = 65; char4 <= 90; char4++) {
                                for (let char5 = 65; char5 <= 90; char5++) {
                                    for (let char6 = 65; char6 <= 90; char6++) {
                                        const key_guess = String.fromCharCode(char1, char2, char3, char4, char5, char6);
                                        const guess = `${password}_${key_guess}`;

                                        const shasum = crypto.createHash('sha1');
                                        shasum.update(guess);
                                        const hashed_guess = shasum.digest('hex');

                                        if (hashed_guess === flag) {
                                            resolve(key_guess);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            });
        }

        const NUMBER_OF_CORES = 6;
        const promiseList = [];
        let startCharAscii = 65;

        // 6 cores
        for (let i = 0; i < NUMBER_OF_CORES; i++) {
            // split into 5, 5, 4, 4, 4, 4
            // btwn cores 0, 1, 2, 3, 4, 5

            // core 0: [65, 69]
            // core 1: [70, 74]
            // core 2: [75, 78]
            // core 3: [79, 82]
            // core 4: [83, 86]
            // core 5: [87, 90]

            if (i === 0 || i === 1) {
                // 5 letters
                promiseList.push(guessPromise(startCharAscii, startCharAscii + 4));
                startCharAscii += 5;
            } else {
                promiseList.push(guessPromise(startCharAscii, startCharAscii + 3));
                startCharAscii += 4;
            }
        }

        await Promise.all(promiseList);
        resolve(promiseList.find((x) => x !== undefined));
    });
}

(async () => {
    console.time(`time`);
    console.log(await guessKey(flag, password));
    console.timeEnd(`time`);
})();

But pushing the pending promises into the list seems to take forever, which shouldn't happen because it's not fulfilled yet. Am I missing something or does asynchronous operations in nodeJS not utilize multi-cores?

Yash Chitroda
  • 645
  • 4
  • 8
  • 27
CXY
  • 33
  • 8
  • 2
    Javascript code is single-threaded. To achieve what you want, use worker threads. – CherryDT Sep 01 '21 at 03:48
  • Concurrency is not the same as async. Node runs in an event loop on a *single thread*. Without awaiting an async call, you just tell node to "keep looping" and check on me next time around. If you await an async call, you essentially halt that single thread by telling Node to wait here until I'm done. A "promise" essentially just tells node that when you **do not** await an async call (node checks on you each time around) you may/may not have something next time around but eventually you promise to have something. (at a high level)... – Matt Oestreich Sep 01 '21 at 04:04
  • You could have 64 cores and 1 million promises but unless you use worker threads, your node code will only ever utilize a single thread on a single core. – Matt Oestreich Sep 01 '21 at 04:09
  • I see.... Do you guys have an example i can follow for multi-threading local calculations? – CXY Sep 01 '21 at 05:26

0 Answers0