【问题标题】:Recursion - Cracking random generated password递归 - 破解随机生成的密码
【发布时间】:2021-07-03 20:39:33
【问题描述】:

所以我找到了破解生成的 5 位密码所需的尝试次数,但是它使用 while 循环而不是递归来完成。我减少了字母的数量,只是为了让它运行得更快并测试代码。我需要进行哪些更改才能使用递归而不是 for/while 循环来破解密码?到目前为止,这是我的全部代码:

//imports
import java.util.Scanner;
import java.util.Random;

class Main {
public static Random rr = new Random();

public static void main(String[] args) {
    // Letters for the random generated password
    // Variables
    String letters = "abcdefghijklmnopqrstuvwxyz1234567890";
    int PASSWORD = letters.length();
    // While statement to allow user to keep generating passwords
    while (true) {
        String password = "";
        Scanner input = new Scanner(System.in);
        // Print menu and uses 1 to generate password
        System.out.println("Press 1 to generate a random password");
        // Takes user input
        int UserOption = input.nextInt();
        // If user input equals 1
        if (UserOption == 1) {
            // Generate a 5-character passwords from the letters in the String
            //Print text is outside the loop to prevent it from printing it more than once in one try
            System.out.println("Your password is: ");
            for (int i = 0; i < 5; i++) {
                password = password + letters.charAt(rr.nextInt(PASSWORD));
            }
            //To print the password and the number of attempts it took
            System.out.println(password);
            passCracking(password, letters, 0, "");
        }
        // If user input is anything except 1
        else if (UserOption != 1) {
            // Print error
            System.out.println("Error");
        }
    }
}
// Method that creates random 5 digit strings and checks if it matches with the password
//Password Generator
private static String comparePass(String characters) {
    String comparePass = "";
    for (int i = 0; i < 5; i++) {
        comparePass = comparePass + characters.charAt(rr.nextInt(characters.length()));
    }
    return comparePass;
}
//Recursive Method 
private static int passCracking(String password, String characters, int tries, String check) {
    //Base Case
    //If the password matches then return 0 to let the loop know we found the match and ends cracking the password
    if (check.equals(password)) {
        return 0;
    }
    //After checking it once, it checks again but if it doesn't match return -1 and does backtrack and calls upon the method again with different password combination
    else if (!check.equals("")) {
        if (!check.equals(password)) {
            return-1;
        }
    }
    //While loop where it keeps looping when its not the correct password
    while (true) {
        check = comparePass(characters);
        if (passCracking(password, characters, tries++, check) == 0) {
            //Print statement for number of attempts
            System.out.println("It took " + tries + " tries to crack the password");
            //Returns zero
            return 0;
        }
        //Add one to the attempt counter for every attempt in cracking the password
        tries++;
    }
}
}

【问题讨论】:

  • 如果您可以检查每个单独的字节是否成功/失败,然后根据结果继续/回退,递归将是有意义的。如果您必须比较整个 5 字节字符串,IMO 就没有任何意义..
  • 我同意你的观点,这就是我之前所做的,但是我想知道是否可以将整个 5 字节字符串与其他临时字符串进行比较作为尝试。你对我该怎么做有什么想法吗?

标签: java recursion passwords brute-force


【解决方案1】:

这是一个(主要是)递归解决方案,它检查给定charset 中字符的每个排列,直到密码maxPwdLength 的某个最大长度。您仍然可以用额外的递归层替换 for 循环。

public class Main {

    public static void main(String... args) {
        String charset = "abcdefghijklmnopqrstuvwxyz1234567890";
        String pwd = crackPassword("", 5, charset);
        System.out.println(pwd);
    }

    public static boolean checkPassword(String guess) {
        String ACTUAL_PASSWORD = "pwd01";  // Whatever the actual password is
        return guess.equals(ACTUAL_PASSWORD);
    }

    public static String crackPassword(String currentGuess, int maxPwdLength, String charset) {
        if (checkPassword(currentGuess)) {
            return currentGuess;  // This means we cracked the password
        }
        if (currentGuess.length() == maxPwdLength) {
            return null;
        }
        
        for (int i = 0; i < charset.length(); i++) {
            String nextGuess = currentGuess + charset.charAt(i);
            String result = crackPassword(nextGuess, maxPwdLength, charset);
            if (result != null) {
                return result;
            }
        }
        return null; 
    }
}

这里更大的问题是你真的想对这个问题使用递归吗?递归可以带来一些优雅的解决方案,但函数调用不是免费的,因此使用递归进行大量调用会损害性能。在这种情况下,迭代解决方案可能会更高效。

【讨论】:

  • 我完全同意你的看法,但是对于这个任务,它需要使用递归来破解密码。
  • @UO23 够公平的。这个答案应该会让你走得很远。我为你做作业是不谨慎的,因为那会剥夺你的学习经验。也就是说,如果您需要在没有任何循环的情况下执行此操作,将 for 循环转换为递归函数并不难。与其向上计数,不如将不断减小的值传递给递归函数,然后在达到 0 或破解密码时开始返回调用堆栈。
猜你喜欢
  • 1970-01-01
  • 2010-09-08
  • 2016-10-04
  • 2012-11-06
  • 2019-08-03
  • 2015-04-13
  • 2012-07-28
相关资源
最近更新 更多