3
\$\begingroup\$

THIS IS JUST FOR LEARNING PURPOSES. I WON'T BE USING THIS TO HACK ANYONE.

Here is a small algorithm I made to crack a password. This is just the background of a more complex code I'm going to make.

To be honest, this code is TERRIBLY written, so I need help on making it more efficient and flexible. It is limited to 5-characters password and not easy to expand.

#include<algorithm>
#include<iostream>
#include<string>
#include<vector>

std::string checkCharacters = {
    '%',
    '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',
    '1','2','3','4','5','6','7','8','9','0'
};

std::string search(std::string password) {
    for (int a = 0; a < checkCharacters.size(); a++)
        for (int b = 0; b < checkCharacters.size(); b++)
            for (int c = 0; c < checkCharacters.size(); c++)
                for (int d = 0; d < checkCharacters.size(); d++)
                    for (int e = 0; e < checkCharacters.size(); e++)
                    {
                        std::string checkString = "";
                        checkString += checkCharacters[a];
                        checkString += checkCharacters[b];
                        checkString += checkCharacters[c];
                        checkString += checkCharacters[d];
                        checkString += checkCharacters[e];

                        checkString.erase(std::remove(checkString.begin(), checkString.end(), '%'), checkString.end());

                        if (checkString == password)
                            return checkString;
                    }

    return "TARGET_PASSWORD_NOT_FOUND";
}

int main() {
    while (1) {
        std::string password;
        std::cout << "Enter password : ";
        std::cin >> password;
        std::cout << "Your password is : " << password << std::endl;
        std::string attempt = search(password);
        std::cout << attempt << std::endl << std::endl;
    }
}
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Generating all the possible passwords (if this is what you need for your other use-cases) is a special case of a more general problem: make all subsets of length k from a set of size n. It might be a good learning experience to try to write such a general code for example using a simple recursive method and with templates to make your method work for arbitrary sets and arbitrary password-lengths k. \$\endgroup\$
    – Winther
    Apr 17, 2017 at 2:00
  • \$\begingroup\$ @Winther, or one can just use std::next_permutation in a loop \$\endgroup\$ Apr 17, 2017 at 8:54
  • 2
    \$\begingroup\$ @Incomputable That won't work here. std::next_permutation gives you the next permutation of the current word but it does not add or remove letters from the word. \$\endgroup\$ Apr 17, 2017 at 16:28
  • 1
    \$\begingroup\$ @Dat I don't think anybody is worried about you cracking passwords with this. It would take longer than the current existence of the universe before it cracked any real password system. \$\endgroup\$ Apr 17, 2017 at 16:30
  • \$\begingroup\$ how to chage delay status / live count.? \$\endgroup\$ Jun 20, 2021 at 4:18

1 Answer 1

4
\$\begingroup\$

This is a critique, and a rewrite of the code you showed, that is, the code for checking if a given password only contains characters from a given character set; for an actual brute force password cracker, see e.g. this question.


I think you should look at the problem a bit differently.

Why don't you go through the characters in the password, and check if every character is in the set of allowed characters?
If you get that every character of the password is in the set of allowed characters, then the password is valid, otherwise it isn't.

I'd implement this in the following way.

#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<numeric>

const static std::set<char> charSet = {
    '%',
    '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',
    '1','2','3','4','5','6','7','8','9','0'
};

bool checkPassword(const std::string password) {
  return std::accumulate( password.begin(), password.end(), true,
    [](bool acc, char c) { return acc && charSet.find(c) != charSet.end(); } );
}

int main() {
  for (;;) {
    std::string password;
    std::cout << "Enter password : ";
    std::cin >> password;
    std::cout << "Your password is : " << password << std::endl;
    if(checkPassword(password)) {
      std::cout << "VALID" << std::endl << std::endl;
    } else {
      std::cout << "INVALID" << std::endl << std::endl;
    }
  }
  return 0;
}

This will work with passwords of any length.
Set lookups have logarithmic complexity, so checking a password of length \$n\$ given a character set of size \$m\$ should be \$\mathcal O(n\cdot \log(m))\$.

\$\endgroup\$
7
  • \$\begingroup\$ @JerryCoffin That's why I wrote 'linear time in its [the password's] length'! Isn't checking a password actually \$O(Nlog(M))\$, since set lookups have logarithmic complexity? Oh my... why did I write that sets have constant lookup time.. thanks for making me notice that. \$\endgroup\$ Apr 17, 2017 at 1:40
  • \$\begingroup\$ @JerryCoffin Thank you again, it should be fixed now. \$\endgroup\$ Apr 17, 2017 at 1:46
  • 1
    \$\begingroup\$ One other point: instead of using std::accumulate, I'd probably use std::all_of here. return std::all_of(pw.begin(), pw.end(), [](char c) { return charSet.find(c) != charSet.end(); }); \$\endgroup\$ Apr 17, 2017 at 2:30
  • \$\begingroup\$ It would be better to use a std::bitset, and just check whether the bit is set. Smaller and vastly more efficient. \$\endgroup\$ Jun 20, 2021 at 13:56
  • \$\begingroup\$ Why is your checkPassword taking its string argument by value? \$\endgroup\$
    – JDługosz
    Jun 21, 2021 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.