找出一个可变长度的字符串?
Posted
技术标签:
【中文标题】找出一个可变长度的字符串?【英文标题】:Figure out a String of variable length? 【发布时间】:2011-08-25 22:02:47 【问题描述】:我有一个字符串的 MD5 哈希,存储为 String
。我正在写一个小程序,通过蛮力找出原始字符串。
我想遍历char
的一个子集。
下面的代码适用于String.length() == 0
。
我不知道如何编辑此代码以使用可变长度String
s。我觉得我在递归的正确轨道上,但不能再进一步了。
我有以下代码:
public void attempt(String initial, String 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);
注意:我应该提到这是针对 MD5 的学术研究。
【问题讨论】:
如果这是您的实际代码而不是示例,您需要在其中添加深度检查(否则您只会生成充满空格的字符串,直到您用完堆栈)并且您需要返回匹配成功,并在您的尝试调用中对此进行测试,以便您在找到匹配项时真正停止。但是您可能想研究尽可能多地优化 MD5 函数,或者以某种方式在许多 CPU 或 GPU 上并行运行散列 - 这是迄今为止您最慢的一步。除了奇怪的简单情况,您永远找不到这样的匹配项 - 这将花费太长时间。 请修复您显示的源代码,它不完整。 我修正了第一段的措辞 首先运行一些关于您需要运行的 MD5 检查数量的计算。粗略估计 MD5 需要多长时间 -> 惊讶于您的计算需要多长时间。 【参考方案1】:您正在执行“Depth first”搜索(并且深度无限!),如果您不添加一些深度检查,这几乎肯定会失败(耗尽您的堆栈)。
你应该可能更好可能想做一个Breadth first search:你的循环应该首先尝试所有导致添加字符的组合,然后才尝试递归调用每个增强字符串的方法。
在任何情况下,您都应该始终添加一些深度检查。
已编辑:三思而后行,我不太确定您是否应该先坚持深度。广度优先在这里仅适用于较小的深度和组合(字符范围)。一种可能的实现方式
// 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;
【讨论】:
我不确定我是否理解其中的含义。我添加了 100 的深度检查,但最终得到了一长串 100 个空格。如何修改它以尝试:a、b、c、aa、ab、ac、ba... 等等? 不客气。但请记住,这具有随深度呈指数级增长的空间,它可能仅对小尺寸有效。在其他地方,采用原始(深度优先)方法- 适当注明。一个简单的 3 个字符的字符串需要 10 多秒。奇怪的是,空间的解决速度要快得多。这无疑是因为它们是 char 序列中的“第一” 我添加了一个深度呼吸实现 - 未经测试 深度优先的实现,奇怪的是,在“尝试”字符串上需要一个 .trim()(方法的第 7 行)【参考方案2】:你们中的第一个不返回结果...
其次,您首先在无限空间上进行深度(它永远不会结束......)
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;
这是一个有界深度优先,意味着它不会比深度更进一步递归(当它找不到任何东西时返回 null
以下可用于遍历整个空间,深度可达 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
我在 10000 的递归上设置了一个最大大小,以使其在可预见的将来某个时候结束
【讨论】:
以上是关于找出一个可变长度的字符串?的主要内容,如果未能解决你的问题,请参考以下文章