Brute-Force java递归密码破解

时间:2016-06-04 10:32:47

标签: java recursion backtracking brute-force

我已经接受了另一个家庭作业,我现在已经开始了一个星期了: 我已经获得了一个只在给定长度内创建a-z密码的类。

public class Password {
private String _password = "";

// Constructor that generates a password
public Password(int length) {
    Random generator = new Random();
    for (int i = 0; i < length; ++i) {
        this._password = this._password + (char) (generator.nextInt(26) + 97);
    }
}

//Method that compares a given string to the password
public boolean isPassword(String st) {
    return st.equals(this._password);
}
}  

规则:

  • 如果要使用String类,则只允许以下内容:charAt,equals,length,substring。
  • 您必须使用递归。
  • 您不能使用26个递归调用。
  • 没有支持方法。
  • 没有数组。
  • 没有静态变量。
  • 重载没问题。

这是我到现在所得到的:

public static String findPassword(Password p, int length) {
    String pswd= "";
    char char2Check = 'a';

    if (length == 0) {
        return "";
    }
    else {
        return findPassword(p,length, pswd, char2Check);
    }
}

public static String findPassword(Password p,int length, String pswd, char char2Check) {
    if (pswd.length() < length) {
            pswd+= char2Check;
            pswd = findPassword(p,length,pswd,char2Check);
        if (pswd.length() < length) {
            if (pswd.length() == 0) {
                if (char2Check == 'z') {
                    return pswd;
                }
                if (char2Check < 'z') {
                    char2Check++;
                    pswd += char2Check;
                    return findPassword(p, length, pswd, char2Check);
                }
            }
            else {
                if (char2Check == 'z') {
                    return pswd.substring(0, pswd.length() - 1);
                }
                if (char2Check < 'z') {
                    pswd = pswd.substring(0, pswd.length() - 1);
                    char2Check++;
                    pswd += char2Check;
                    return findPassword(p, length, pswd, char2Check);
                }
            }
        }
    }
    if (pswd.length() == length) {
        System.out.println(pswd);
        if (p.isPassword(pswd)) {
            return pswd;
        }
        if (char2Check < 'z') {
            pswd = pswd.substring(0, pswd.length() - 1);
            char2Check++;
            pswd+= char2Check;
            return findPassword(p,length,pswd,char2Check);
        }
        if (char2Check == 'z'){
            return pswd.substring(0, pswd.length() - 1);
        }
    }
    return pswd;
}
问题是:

如果第一个字符是'r',它不会在它之后检查a,b或c,它会直接转到s,t,u ...

还有一些问题,但一旦这个问题消失了,我认为其余的问题会更容易解决..

这里是输出的粘贴: http://pastebin.com/CK9AyKUi

希望有人可以帮助我:)

4 个答案:

答案 0 :(得分:4)

你为了简单的事情而花了很多时间:生成长度为n的所有字符串,只包含a-z字符。

有关演出的说明:当您想要执行大量StringBuilder和删除字符时,请使用String代替append。字符串是不可变的,因此它们会在您的代码中反复复制。

现在,关于递归,你只需要考虑两件事:你的一般情况是什么?你的停止条件是什么?

这里,停止条件很简单:真实密码和当前试用版具有相同的长度。如果试验是正确的,那么将其归还;否则在递归中上升。第二个停止条件:已经尝试了当前前缀的所有可能性,并且没有匹配,然后在递归中上升。

一般情况也很简单:给定当前前缀,尝试附加每个可能的字母a-z并添加一级递归。

现在,您可能希望再次使用这些线索(提示:重新开始比尝试修复当前代码更容易)。我的解决方案如下,但你可以拿出自己的解决方案:

public static String findPassword(Password p, int length) {
    return findPassword(p,length, new StringBuilder());
}

public static String findPassword(Password password, int length, StringBuilder str) {
    // Stop condition, password and trial have same length
    if (length == str.length()) {
        if (password.isPassword(str.toString())) {
            return str.toString();
        } else {
            return "";
        }
    }

    String s;

    for (char c = 'a'; c <= 'z'; c++) {
        // Add a new character to the given prefix
        str.append(c);
        // Try to find a password for the new prefix
        s = findPassword(password, length, str);
        if (!s.equals("")) {
            return s;
        }
        // Didn't work out, remove the character
        str.deleteCharAt(str.length()-1);
    }
    // All chars have been tried without success, go up one level
    return "";
}

答案 1 :(得分:1)

我不会给你解决方案。但假设字母表是&#34; abc&#34;如果要查找长度为3的密码,则必须对此进行编程:

a -> aa -> aaa 
|     |      | 
|     |    aab 
|     |      | 
|     |    aac 
|     |        
|    ab -> aba 
|     |      | 
|     |    abb 
|     |      | 
|     |    abc 
|     |        
|    ac -> aca 
|            | 
|          acb 
|            | 
|          acc 
|              
b -> ba -> baa 
|     |      | 
|     |    bab 
|     |      | 
|     |    bac 
|     |        
|    bb -> bba 
|     |      | 
|     |    bbb 
|     |      | 
|     |    bbc 
|     |        
|    bc -> bca 
|            | 
|          bcb 
|            | 
|          bcc 
|              
c -> ca -> caa 
      |      | 
      |    cab 
      |      | 
      |    cac 
      |        
     cb -> cba 
      |      | 
      |    cbb 
      |      | 
      |    cbc 
      |        
     cc -> cca 
             | 
           ccb 
             | 
           ccc

每个递归步骤必须检查两条路径。

  • ->,如果密码不够长,请尝试附加'a'
  • |,只要它不是字母表中的最后一个字符,就会递增最后一个字符。

这两条路径都有一个需要注意的停止条件:密码长度&amp;字母长度。

答案 2 :(得分:0)

 private static boolean findPassword(Password p, String pswd, int length) {

    if (length == pswd.length()) {
        if (p.isPassword(pswd))
            System.out.println(pswd);
        return p.isPassword(pswd);

    }

    String alpha = "abcdefghijklmnopqrstuvwxyz";
    for (int i = 0; i < alpha.length(); i++) {
        if (findPassword(p, pswd + alpha.charAt(i), length)) 
            return true;
    }
    return p.isPassword(pswd);
}

答案 3 :(得分:0)

首先,非常感谢!

你的代码给了我一些好主意 为你修好了:))

我已经更正了你的代码并且它的作品很完美

这里是:

  public static String findPassword(Password p,int length)
  {
      // string and char to be input into the overloading method
      String pswd= "";
      char char2Check = 'a';

      // Checking if the length of the password is 0 so its null
      if (length == 0)
      {
          return "";
      }
      else{
          // going to the overloading method to find the password
          return findPassword(p,length, pswd, char2Check);
      }
  }

  public static String findPassword(Password p,int length, String pswd, char      char2Check)
  {

    // Checking if the length of the password finder is less then the length of the 
    // password we add more chars until they are the same length to check if they're equal
    if (pswd.length() < length)
    {
        pswd+= char2Check;
        pswd = findPassword(p,length,pswd,char2Check);
        char2Check = pswd.charAt(pswd.length() - 1);
        if (pswd.length() < length)
        {
            if (pswd.length() == 0)
            {
                if (char2Check == 'z')
                {
                    return pswd;
                }
                if (char2Check < 'z')
                {
                    char2Check++;
                    pswd += char2Check;
                    return findPassword(p, length, pswd, char2Check);
                }
            }else{
                if (char2Check == 'z')
                {
                    return pswd.substring(0, pswd.length() - 1);
                }
                if (char2Check < 'z')
                {
                    char2Check = pswd.charAt(pswd.length() - 1);
                    pswd = pswd.substring(0, pswd.length() - 1);
                    char2Check++;
                    pswd += char2Check;
                    return findPassword(p, length, pswd, 'a');
                }
            }
        }
    }
    // Checking if the password finder length is the same as the original password
    if (pswd.length() == length)
    {
        System.out.println(pswd);
        // Checking if the two password match, if so we return the password finder.
        if (p.isPassword(pswd))
        {
            return pswd;
        }
        // Checking if the char is not the last char -> z
        if (char2Check < 'z')
        {
            pswd = pswd.substring(0, pswd.length() - 1);
            char2Check++;
            pswd+= char2Check;
            return findPassword(p,length,pswd,char2Check);
        }
        if (char2Check == 'z')
        {
            return pswd.substring(0, pswd.length() - 1);
        }
    }
    return pswd;
}
相关问题