You do a " Depth first " search (and unlimited depth!), It is almost guaranteed to fail (exhausting your stack) unless you add some depth checking.
Perhaps you are better off Quickly search by width : your loop should first try all the combinations, which leads to the addition of a character, and only then, if it does not succeed, try recursively calling the method with each line added.
In any case, you should add some depth check, always.
Edited: Thinking about it twice, Iβm not sure that you should not stick to the depth first. The width here is first blurred here for shallow depths and combinations (character ranges). 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; }
source share