Generating All Possible Combinations of String Characters in JavaScript

Dipo Olanipekun
Geek Culture
Published in
4 min readMay 7, 2021

--

Password Combination

A while ago, I could not access a compressed zip file I made containing some important documents. I must have made a mistake while setting the password for the zip file.

I tried various free software for cracking zip files but none of them seem to work, they were all buggy. So I thought of another solution: What if I can generate all possible passwords ever and try them all?

The list of all possible passwords ever will be infinite except the length of the password and the number of possible characters is limited. I know for sure I could not have entered a password longer than 3 characters long and all the characters are lowercase alphabets. In other words, I need to generate a list of the password not longer than 3 characters and doesn’t contain any other character outside lowercase a to z — 26 characters.

Now, given a list of characters and a minimum and maximum length, the total number of generated passwords will be:

n^a + n^(a+1) + n^(a+2) + … + n^(b-2) + n^(b-1) + n^b

Where:
- n is the number of available characters (n ≥ 1)
- a is the minimum password length (ba ≥ 1)
- b is the maximum password length (nba)

For example:
For a list characters “abcd”, n = 4, a = 2, and b = 4, the total number of generated passwords will be:

4² + 4³ + 4⁴ = 16 + 64 + 256 = 336

This can be demonstrated with a JavaScript function

countCombinations = (n, a, b) => {
a = parseInt(a) || 0;
b = Math.max(parseInt(b) || 0, a);
let count = 0;
if(a) {
for (i = a; i <= b; i++) {
count += Math.pow(n, i);
}
}
return count;
}

In my case, for a list of 26 characters, n = 26, a = 1, and b = 3, the total number of generated passwords will be:

26¹ + 26² + 26³ = 18278

If I test each password in 200 milliseconds, I will get the correct password approximately within an hour.
Now I need to write a JavaScript function to generate the passwords

The function accepts 3 parameters the characters list chars, the minimum password length minLength, and the maximum password length maxLength. A generator function* will be used. This way, we can iterate over the passwords like an array without exhausting the allocated memory even if the size of the passwords is infinite. You can read more on Javascript Generator functions on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator

function* charCombinations (chars, minLength, maxLength) {
// Yield the passwords.
}

The passwords will be generated for each password length (minLength -> maxLength)

for (i = minLength; i <= maxLength; i++) {
// Generate all possible combinations for the current length
}

The first password for the current password length is generated by the repetition of the first character chars[0].

word = (chars[0] || '').repeat(i);
yield word;

Other possible combinations for the current password length are generated with an iteration of the total possible combinations which can be calculated by the total number of characters raised to the power of the current password length.

for (j = 1; j < Math.pow(chars.length, i); j++) {
// Yeild a word for each iteration
}

The password is treated like a number. Imagine a character list of 10 characters 0–9 and length 3. Below is an example of the first 12 combinations.

000
001
002
003
004
005
006
007
008
009
010
011

Consider each line an iteration of a possible combination and each combination is generated with the following rule.
- The last digit is flipped on every iteration.
- When a digit has flipped through all the characters, the next digit to the right is flipped.
By the time the iteration is complete, we would have generated all the possible combinations for the current length 3.
The same logic applies to our function but the characters do not have to be limited to 0–9. It could be any list of characters.

We can achieve the logic above in Javascript with the code below.

//Make iteration for all indices of the word
for(k = 0; k < i; k++) {
//check if the current index char need to be flipped
if(!(j % Math.pow(chars.length, k))) {
// Flip matched index char to the next
let charIndex = chars.indexOf(word[k]) + 1;
char = chars[charIndex < chars.length ? charIndex : 0];
word = word.substr(0, k) + char + word.substr(k + char.length);
}
}
// yeild the combination
yield word

You can find the full code in the Github Gist below

A common application of this method is to crack weak passwords. The example below will crack all passwords not longer than 3 characters.

let passwords = charCombinations('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ !"#$%&\'()*+,-./:;<=>?@[\\]^7_`{|}~', 3);let password = {};while(password = passwords.next()) {
//tryPassword(password.value);
}

Cracking a longer password will result in a longer password list and ultimately a longer time to iterate over the list. While the above example will generate a list of 894048 passwords, increasing the max password length to 4 will generate 85828704. The minimum password length and the character list can be adjusted to optimize the password list for specific targets.

The function can be still be further extended to support ascending/descending sorting and skipping of the iterations to a specific index.

Thanks for reading.

--

--

Dipo Olanipekun
Geek Culture
0 Followers

I am a software developer who loves expressing real life problem and solving them using computer logic.