Brute Force java递归密码破解



我接到了另一项家庭作业,我已经想了一周了:我得到了一个类,它只创建给定长度的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

希望有人能帮我:)

您为一些本应简单的事情付出了巨大的代价:生成所有长度为n且仅包含a-z字符的字符串。

关于性能的注意事项:当您想要执行大量的append和删除字符时,请使用StringBuilder而不是String。字符串是不可变的,因此它们会在代码中一次又一次地复制。

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

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

一般情况也很简单:给定当前前缀,尝试附加每个可能的字母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 "";
}

我不会给你解决方案。但假设字母表是"abc",并且你想找到长度为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

每个递归步骤都有2条路径需要检查。

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

这两条路径都有一个必须注意的停止条件:密码长度&字母表长度。

首先感谢!

u'r代码给了我一些好主意为您修复:)

我已经更正了你的代码,它的工作完美

它在这里:

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;
}
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);
}

最新更新