Playfair Hillclimbing破解

时间:2014-01-01 20:31:04

标签: python algorithm cryptography hill-climbing

我正在编写一个python脚本来破解一个playfair密码,只有密文。 首先,我生成大约30-100个解密密钥并在密文上运行它们,将每个解密密钥放在它的有向图频率上。对于下一代'代'/迭代,我复制得分最高的那些。然后它们发生变异(字母在5x5网格中交换位置)并重新添加到下一次迭代,再次排名,依此类推。

我注意到脚本经常找到一个局部最大值 - 一个给出类似分布的键,但不是真正的交易。我认为问题的解决方案是为密钥填充引入更多变化(在脚本末尾,所有这些变量几乎相同)。

我尝试通过向每一代添加几个完全随机的密钥来实现它,但它们几乎立即被淘汰。做一个更好的方法是什么?我也想过像模拟退火这样的策略,但不知道它们会有多大的帮助。

编辑:按要求提供样本密文(关键字:playfair示例)

['p', 'l', 'a', 'y', 'f']
['i', 'r', 'e', 'x', 'm']
['b', 'c', 'd', 'g', 'h']
['k', 'n', 'o', 'q', 's']
['t', 'u', 'v', 'w', 'z']
  
    

as el ul ul vi ne uz qk dm kz qe ca qe tb qc pv zb md nv om lo gv qo od er qc zg pv vk ov or iw zg ro nz ge ro af yp qe zi lo rk pr ad xl dl ix cl qr rk dq vu sa zb xv qe ho dm dn ok eb xe do bm iz kd de as kv ef kc rd lv om dm vy km ur et xe aq zb xe tx om rt gh rk hc fg mk py dr qo af zs xv nv ac df ad dl yr do bm ef pm zs lo ce yl ai ca nv ca fy wi dm ov ne tx zb bm kn ul bn ar km uz fo ka ro do gp lo kv dm ml qe zi lo rk pr ad xl tx zb le nv oc py dr lo le le dx xa mo pr oi yp en dy oc dk zb as kv ix ol pr dr oq pb dr gb eo ak vg xe do df re zb pv nl cr do ya an ad iu dm re dm eo qm dm am pu ad xl nl er nv kz qn oq yg df pb uz fo ya ay dk vu lo gd ex ip ya bp up xv yf nv vk pz dm vq vo vk pr kz ro

  

2 个答案:

答案 0 :(得分:3)

应用于加密的Hillclimbing algo原则的工作原理如下:

  1. 随意制作一把钥匙(在ramdom上制作25个字母的字母表),并用你的有向图评分确定适合度。称之为'父母'
  2. 对父级进行一些更改以生成“子”键(5x5网格键表中的随机交换并不是那么糟糕)并使用您的有向图评分函数来衡量其适应性。
  3. 如果孩子比父母更健康,那就做孩子吧 新的父母,并免除旧的
  4. 回到(2),除非过去1000没有改进 在这种情况下的变化可以追溯到(1)
  5. 这是避免在双向评分函数的局部最大值中被阻止的方法。

    如果你想要比Hillclimbing更好的结果,你必须开发一个模拟退火算法。此外,基于三卦或4克的评分函数具有较少的局部最大值。 如果你想更快地破解它,你将从python转向C / C ++。

    HillClimbing和Simulated Annealing算法可用于破解Playfair密码以及所有其他基于5 * 5网格的密码,以及简单的替换密码和Vigenere密码。

    Playfair密码的一个重要之处在于它很弱:5x5网格的所有圆形水平或垂直排列都是等效密钥。因此,该密码的算法收敛速度更快。

    要使父母字母使用以下内容:

    alpha='ABCDEFGHIKLMNOPQRSTUVWXYZ'
    used=[0]*25;parent=['']*25
    for i in range(25):
        j=randrange(25)
        while used[j]:j=randrange(25)
        parent[i]=alpha[j];used[j]=1
    

    playfair解密功能:

    def DEplayfair(a,key):
    l=[];order={}
    for k in range(25):order[key[k]]=k
    for i in range(0,len(a),2):
        ord1=order[a[i]]
        raw1=ord1//5
        col1=ord1%5
        ord2=order[a[i+1]]
        raw2=ord2//5
        col2=ord2%5
        if raw1==raw2:
            l.append(key[5*raw1 + (col1 + 4)%5])
            l.append(key[5*raw2 + (col2 + 4)%5])
        elif col1==col2:
            l.append(key[col1 + 5*((raw1 + 4)%5)])
            l.append(key[col2 + 5*((raw2 + 4)%5)])
        else:
            l.append(key[5*raw1 + col2])
            l.append(key[5*raw2 + col1])
    return ''.join(l)
    

    对于SA算法,您可以在以下方面找到SA的基本原则: http://en.wikipedia.org/wiki/Simulated_annealing

    第二次世界大战期间,美国海岸警卫队使用了Playfair密码,并且有一个着名的历史Playfair密码: http://practicalcryptography.com/ciphers/playfair-cipher/

    PS:playfair密码示例中主角的名称是Alice。

答案 1 :(得分:0)

如果我正确地阅读了你的问题,你会改变你的一代,但你不会重新组合它。也许你可以这样做:

  1. 第0代是随机密钥。
  2. 选择排名最高的n个密钥,剩下的就死了。
  3. 将幸存者杂交在一起。低百分比的重组突变。
  4. 冲洗并重复。
  5. 重组可能如下所示:

    1. 父母是A和B,他们生育n个后代。
    2. 对于每个后代,选择0< = x< = y< 25(可能具有约束y-x> c)。后代的关键是A [:x] + B [x:y] + A [y:]。