Problem
I have created a brute-force algorithm class in C# and I was wondering if I could speed up the process of creating a new string. There are two methods inside the class: one returns the brute-force string and one returns the number of strings created.
public class BruteForce
{
int IntPasswordsGenerated = 0;
public char[] CharList = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
public List<int> IntList = new List<int> { 0 };
public string GenerateString()
{
int Number = IntList.Count - 1;
IntPasswordsGenerated++;
if (IntPasswordsGenerated == 1) return CharList[0].ToString();
do
{
IntList[Number]++;
if (IntList[Number] == CharList.Length && Number == 0)
{
IntList[Number] = 0;
IntList.Add(0);
break;
}
else if (IntList[Number] == CharList.Length)
{
IntList[Number] = 0;
Number--;
continue;
}
else
{
break;
}
} while (true);
string BruteForceString = "";
foreach (int CurrentInt in IntList)
BruteForceString += CharList[CurrentInt];
return BruteForceString;
}
public int PasswordsGenerated()
{
return IntPasswordsGenerated;
}
}
Solution
What you have implemented is a back-to-basics number-system in base 62 Your IntList
List is a mechanism of having the equivalent of “units”, “tens”, “hundreds”, except you are in base 62 so it’s “units”, “sixty-twos”, …..
When you increment a value, and it overflows, you then set it back to zero, and increment the next column instead.
In addition, you have a special case for the first time around, where you have to bypass the logic to ensure you have the right initial value returned.
So, there’s a trick for the first time around that’s easy to implement. The trick is to think of the array as holding the “next” value to return. Your code then becomes:
string BruteForceString = "";
foreach (int CurrentInt in IntList)
BruteForceString += CharList[CurrentInt];
// Now calculate the **next** password
......
return BruteForceString;
Note how your initial array already contains the “next” password when initialized. Then, you can convert that to a string, and then increment the array to be ready for the next call.
But, I want to suggest that you are doing it all horribly wrong… 😉
What you should be doing is using a simple long
value to store your next value, and then using integer division and modulo to work your base-62 system.
Additionally, your variable names are quite horrible…. but that’s OK, we will get rid of them all except the worst….
private ulong IntPasswordsGenerated = 0;
public string GenerateString()
{
string password = "";
ulong base = CharList.Length;
// get the current value, increment the next.
ulong current = IntPasswordsGenerated++;
do
{
password = CharList[current % base] + password;
current /= base;
} while (current != 0);
return password;
}
The magic is almost entirely in this line here:
ulong current = IntPasswordsGenerated++;
hat takes a copy of the “next” password, and then afterwards increments what the next password will be.
Using division and modulo is likely a lot faster than the multiple loops required to check and validate the multiple array elements in your custom number system.
Finally, by taking a copy of the next password, and by keeping the password as a single ulong
instance variable, it becomes relatively simple to lock on a small section of code and then make your method able to run in multiple threads… allowing you to brute force more passwords at once though parallel processing. All you need to do that is drop the ulong
to a long, and then use the Interlock.increment()
method to do a thread-safe, atomic increment (assuming you have a 64-bit machine).
You are always writing the type of variables inside the variables’ names, for example: IntPasswordsGenerated
Remove them as the compiler already takes care of types for You.