Figure out a String of variable length?
I have the MD5 hash for a String, stored as a String
. I'm writing a small program to find out the original string by brute force.
I'd like to loop through a subset of char
.
The code below works for when String.length() == 0
.
I can't figure out how to edit this code to work with variable-length String
s. I feel like I'm on the right track with recursion, but can't go any further.
I have the following code:
public void attempt(String initial, St开发者_运维百科ring md5) {
for (char c = ' '; c < '~'; ++c) {
attempt = initial + Character.toString(c);
generatedMd5 = generateMD5(attempt);
System.out.println(attempt);
if (hashesMatch(md5, generatedMd5)) {
break;
} else attempt(attempt, md5);
}
}
Note: I should mention this is for an academic study on MD5.
You are doing a "Depth first" search (and of unlimited depth!), this is almost guaranteed to fail ( exhausting your stack) if you do not add some depth check.
You should probably better might want to do a Breadth first search : your loop should first try all the combinations that results in adding a character, and only then, if no success, try to recursively call the method with each augmented string.
In any case, you should add some depth check, always.
Edited: thinking it twice, I'm not so sure you should not stick with depth first. Breadth first is only rasonable here for small depths and combinations (character ranges). A possible implementation
// Breadth first returns null if not found
public String bruteforce(List<String> prefixes, String md5,int availdepth) {
if(availabledepth<0) return null;
List<String> newprefixes = new ArrayList<String>();
for(String prefix : prefixes) {
for (char c = ' '; c < '~'; ++c) {
String attempt = prefix + Character.toString(c);
generatedMd5 = generateMD5(attempt);
if (hashesMatch(md5, generatedMd5))
return attempt;
newprefixes.add(attempt);
}
}
// no success in this level go for next
return bruteforce(newprefixes,md5,availddepth-1);
}
// Depth first - returns null if not found
public String bruteforce(String prefix, String md5,int availdepth) {
if(availdepth <= 0) return null;
for (char c = ' '; c < '~'; ++c) {
String attempt = prefix + Character.toString(c);
if (hashesMatch(md5, generateMD5(attempt)))
return attempt;
String res = bruteforce(attempt, md5, availdepth-1);
if(res != null) return res;
}
return null;
}
first of you don't return a result...
second you are doing depth first on a infinite space (it's never going to end...)
public String attempt(String initial, String md5,int depth) {
if(depth < 0)return null;//failed backtrack
for (char c = ' '; c < '~'; ++c) {
attempt = initial + Character.toString(c);
generatedMd5 = generateMD5(attempt);
System.out.println(attempt);
if (hashesMatch(md5, generatedMd5)) {
return attempt;//success
} else {
String res = attempt(attempt, md5,depth-1);
if(res!=null)return res;
}
}
}
this is a bounded depth first meaning it won't recurse further than depth (and return null when it can't find anything
the following can be used to go over the entire space up to depth 10000
String attempt(String initial,String md5){
for(int i = 5;i<10000;i++){
String res = attempt(initial,md5,i);
if(res!= null)return res;
}
return null;//let's not go overboard on recursion
}
I put a max size on the recursion on 10000 to make it end sometime in the foreseeable future
精彩评论