Eldar B.
Eldar B.

Reputation: 1347

Brute Force Algorithm Prints Only 0

I am creating a Brute Force Algorithm (for educational purposes) on C#, and I have met an error.

My way of bruteforce is like a clock - last character in the string goes up from 0 to last character in a character array set in the beggining of the program, when it reaches the end - resets to 0 and increases the previous character by 1 and so on.

Yet, the code below prints only 0's:

// Array with characters to use in Brute Force Algorithm.
    // You can remove or add more characters in this array.
    private static char[] fCharList =
    {
        '0','1','2','3','4','5','6','7','8','9','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','C','L','M','N','O','P',
                    'Q','R','S','T','U','V','X','Y','Z','~','!','@','#','$','%','^','&','*','(',')','[',']','{','}','.',',','/','?','\'','|','"',';',':','<','>','\\','=','-','+','`','_'
    };

    private static String password;

    static void Main(string[] args)
    {
        Console.WriteLine("Enter the password: ");
        password = Console.ReadLine();
        Bruteforce();
    }

    // The Bruteforce algorithm
    // Goes like a clock cycle: Last index goes from fCharList[0] to fCharList[fCharList.Length - 1] 
    // then resets and last index -1 increases and so on.

    public static String Bruteforce()
    {

        String currPass = fCharList[0].ToString();
        bool foundPass = false;

        for (int i = 1; !foundPass; i++)
        {
            // If there's a need to increase (foundd fCharList[fCharList.Length - 1] in the String)
            if (currPass.Contains(fCharList[fCharList.Length - 1]))
            {
                //If no need to increase the whole length and reset all the characters
                if (!(currPass.IndexOf(fCharList[fCharList.Length - 1]) == 0))
                {
                    String updateCurrPass = "";
                    for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
                    {
                        updateCurrPass += fCharList[0].ToString();
                    }
                    currPass.Insert(currPass.IndexOf(fCharList[fCharList.Length - 1]) - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt<char>(currPass.IndexOf(fCharList[fCharList.Length - 1]) - 1)) + 1].ToString() + updateCurrPass);
                }
            }
            else // If no cycle ended - continue increasing last "digit"
            {
                currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
            }
            Console.Write(currPass + "  ");

        }
        return "";
    }

I tried all the possible issues with the currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString()); (as I suspected that the problem might occure in the printing process itself), but with no success.

I also tried to trace the code using breakpoints and paper, still nothing. It would be very pleasing if someone can help me solve this problem.

Edit: Below, many suggested the updateCurrPass += fCharList[0].ToString(); should rather be updateCurrPass += fCharList[j].ToString();. I haven't yet checked that option too deep, but to explain better my situation, I want it to work like a clock cycle - when the last digit is the latest character in fCharList, the previous digit increases and so on. The code mentioned resets the digits that have reached the last character. (So, if the string currPass was "0aa___" (_ is the last character), it will become 0ab000) the updateCurrPass adds the 3 0's, while the rest of the the function increases the a to b.

Upvotes: 1

Views: 578

Answers (3)

Rafalon
Rafalon

Reputation: 4515

As noted by @VincentElbertBudiman, you have to use j in your loop and not 0. (or maybe not, I'm unsure if I understand well your algorithm)

But there's something more:

You have to note that in C#, Strings are immutable, meaning currPass.Insert(...) does nothing in itself, you have to reassign the result like currPass = currPass.Insert(...);

But hey, I think you are overcomplicating the algorithm.

What I would've done:

string currPass = fCharList[0].ToString();
bool found = false;
while(!found)
{
    currPass = IncreasePassword(currPass);
    found = CheckPass(currPass);
}

With IncreasePassword:

public static string IncreasePassword(string pass)
{
    bool changed = false;
    StringBuilder sb = new StringBuilder(pass);
    // loop through pass until we change something 
    // or we reach the end (what comes first)
    for(int i = 0; i < pass.Length && !changed; i++)
  //for(int i = pass.Length - 1; i >= 0 && !changed; i--)  
    {
        int index = Array.IndexOf(fCharList, sb[i]);
        // if current char can be increased
        if(index < fCharList.Length - 1)
        {
            // if we have __012 then we'll go on 00112
            // so here we replace the left __ with 00
            for(int j = i - 1; j >= 0 && sb[j] == fCharList[fCharList.Length - 1]; j--)
          //for(int j = i + 1; j < sb.Length && sb[j] == fCharList[fCharList.Length - 1]; j++)
            {
               sb[j] = fCharList[0];
            }
            // and here we increase the current char
            sb[i] = fCharList[index + 1];
            changed = true;
        }
    }
    // if we didn't change anything, it means every char were '_'
    // so we start with a fresh new full-of-0 string
    if(!changed)
    {
        return "".PadLeft(pass.Length + 1, fCharList[0]);
    }
    return sb.ToString();
}

Live example.


Explanations

This will work from left to right the following way:
Say our fCharList is { '0','1','2' } for simplifications.
We'll have:

0
1
2
00
10
20
01
11
21
02
12
22
000
100
200
010
110
210
020
....

Test results

This is what it gives with reversed inputs (as my solution goes the other way around) from Weeble's suggestions:

Input        Output
0            1
1            2
P            Q
_            00
00           10
_0           01
__CBA        00DBA
____         00000

Please note that your fCharList is broken as there's a C instead of K!

Upvotes: 1

Weeble
Weeble

Reputation: 17930

While there are specific problems pointed out by the other answers, may I suggest that your broader problem is that you're trying to do too much at once? You may well be capable of writing this whole algorithm in one piece and tweaking it until it works, but it's both very hard to do this and hard to have confidence in the end that it's correct. You will find it easier to break down the algorithm into smaller functions and test those individually to confirm they do what you expect.

For example, you could break out the part of the algorithm that works out "given the last password I checked, what is the next password in sequence to consider"? This is the core of the algorithm, and it can be separated from the work of iterating through all the possible passwords and testing them against the current one. And it is much easier to test! For example, you can use test data like this:

Input             Expected output
"0"               "1"
"1"               "2"
"P"               "Q"
"_"               "00"
"00"              "01"
"0_"              "10"
"ABC__"           "ABD00"
"____"            "00000"

When you find out that your function doesn't give the right answer for some or all of these tests, you have a much smaller and more specific job to do to figure out what's wrong than trying to debug the whole algorithm at once.

Upvotes: 0

Vincent Elbert Budiman
Vincent Elbert Budiman

Reputation: 309

Did you think because you assign updateCurrPass like this ? :

for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
     updateCurrPass += fCharList[0].ToString();
}

I think it should be involving j or something :

for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
     updateCurrPass += fCharList[j].ToString();
}

Added code :

This below code will do nothing because the function will return the function (instead of changing the object passed by parameters), you should add currPass = currPass.Insert(...) as noted by @Rafalon

else // If no cycle ended - continue increasing last "digit"
{
    currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}

Use this instead :

else // If no cycle ended - continue increasing last "digit"
{
    currPass = currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}

Upvotes: 1

Related Questions