关键词暴力破解

4

我需要找到一个密码密钥。该密钥的长度为10个字符,字母在密钥中的顺序是3,7,2,1,4,5,6,10,8,9。我还知道该密钥的md5值。

因此,我编写了以下代码:

mystring = "abcdefghijklmnopqrstuvwxyz"
for letter3 in mystring:
    for letter7 in mystring[mystring.index(letter3):]:
        for letter2 in mystring[:mystring.index(letter7)]:
            for letter1 in mystring[:mystring.index(letter2)]:
                for letter4 in mystring[mystring.index(letter1):]:
                    for letter5 in mystring[mystring.index(letter4):]:
                        for letter6 in mystring[mystring.index(letter4):]:
                            for letter10 in mystring[mystring.index(leter6):]:  
                                for letter8 in mystring[:mystring.index(letter10)]:
                                    for letter9 in mystring[mystring.index(letter8):]:
                                        strr = "".join([letter1,letter2,letter3,letter4,letter5,letter6,letter7,letter8,letter9,letter10])
                                        if hashlib.md5(strr).hexdigest() == md5:
                                            print "key = " ,strr
                                            break

字符的顺序:

关键点:

|letter1|letter2|letter3|letter4|letter5|letter6|letter7|letter8|letter9|letter10|

按字母顺序排序的关键字:

|letter3|letter7|letter2|letter1|letter4|letter5|letter6|letter10|letter8|letter9|

问题在于时间(一个迭代需要大约6小时的时间)。有没有优化for循环范围的建议?


@QuestionC 抱歉,我不明白你的意思。我应该修改代码以使其更易读吗? - Chaker
不,你的代码是正确的。只是对如何排序字母有点困惑。 - QuestionC
@QuestionC 我希望现在更清楚了。谢谢。 - Chaker
你试过在线哈希破解器吗? - bereal
1
@alik 当然是 a50e38475041f76219748ee22c4377d4 - Chaker
显示剩余6条评论
2个回答

6

解决方案在底部


非常接近了。您需要的是这个...

mystring = "abcdefghijklmnopqrstuvwxyz"
for letter1 in mystring:
    for letter2 in mystring[mystring.index(letter1):]:
        for letter3 in mystring[mystring.index(letter2):]:
            for letter4 in mystring[mystring.index(letter3):]:
                for letter5 in mystring[mystring.index(letter4):]:
                    for letter6 in mystring[mystring.index(letter5):]:
                        for letter7 in mystring[mystring.index(letter6):]:
                            for letter8 in mystring[mystring.index(leter7):]:  
                                for letter9 in mystring[mystring.index(letter8):]:
                                    for letter10 in mystring[mystring.index(letter9):]:
                                        strr = "".join([letter3,letter7,letter2,letter1,letter4,letter5,letter6,letter10,letter8,letter9])
                                        if hashlib.md5(strr).hexdigest() == md5:
                                            print "key = " ,strr
                                            break

那个循环严重减少了迭代次数,因为你搜索的字符数量要少得多。每个循环搜索的字符数量比它的外部循环少。请注意,每个循环都在同一个方向上搜索,这使得它更加有条理。

但是它也非常缓慢,因为mystring.index()是一个很慢的操作。我们可以通过不使用mystring.index()来加快速度...

mystring = "abcdefghijklmnopqrstuvwxyz"

for i1 in range(len(mystring)):
    for i2 in range(i1, len(mystring)):
        for i3 in range(i2, len(mystring)):
            for i4 in range(i3, len(mystring)):
                for i5 in range(i4, len(mystring)):
                    for i6 in range(i5, len(mystring)):
                        for i7 in range (i6, len(mystring)):
                            for i8 in range (i7, len(mystring)):
                                for i9 in range (i8, len(mystring)):
                                    for i10 in range (i9, len(mystring)):
                                        strr = "".join([mystring[i3], mystring[i7], mystring[i2], mystring[i1], mystring[i4], mystring[i5], mystring[i6], mystring[i10], mystring[i8], mystring[i9]])
                                        if hashlib.md5(strr).hexdigest() == md5:
                                            print "key = " ,strr
                                            break

尽管如此,这仍然非常缓慢,因为它需要大量的迭代。

这里的技巧是使用itertools......

mystring = "abcdefghijklmnopqrstuvwxyz"

import itertools

for L1, L2, L3, L4, L5, L6, L7, L8, L9, L10 in itertools.combinations_with_replacement(mystring, 10):
    strr = "".join([L3, L7, L2, L1, L4, L5, L6, L10, L8, L9])
    if hashlib.md5(strr).hexdigest() == 'a50e38475041f76219748ee22c4377d4':
        print ('key = {}'.format(strr))
        break

itertools.combinations_with_replacement()是处理Python中类似A >= B >= C >= &ct的嵌套循环的最快速度的解决方案。


我将解决方案更改为使用combinations_with_replacement而不是combinations。在这里查看区别... https://docs.python.org/2/library/itertools.html - QuestionC
我还将解决方案更新为Python3,因为这是我测试的版本。 - QuestionC
2
我做了和你几乎一样的事情,并发现关键是 do****** - Konstantin
1
不要发答案啊。我们只说它以 d 开头 =) - QuestionC
1
你还可以使用enumerate和切片来实现第二个建议,而不是那个备受诟病的对range进行迭代的方法。 - RoadieRich
显示剩余2条评论

-1

如果你将它编译成机器码,你会发现for循环由四个部分组成。首先,当前迭代整数从内存中加载,给定数组中的字母也被加载。然后执行for循环内的任何内容,最后增加索引并在条件仍然成立时执行条件跳转回for循环的开头。

唯一优化这个过程的方法(虽然我不能确定Python;我已经尝试过优化C的for循环)是摆脱增量部分并使用常量。也就是说,手动布局字母的迭代。也就是说,摆脱for循环,而是复制和粘贴成千上万行代码。这显然不是非常理想和可重用的,我们旨在优化的for循环也消失了。

我想我想说的是,for循环已经非常优化了,因为它是汇编语言中非常基本的东西。毕竟,你正在尝试强制它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接