题解
题目明显提示暴力方法,盲猜是一个简单换位密码,不同于凯撒密码,每个字母对应的密文是完全混乱的:
abcdefghijklmnopqrstuvwxyz
qwertyuiopasdfghjklzxcvbnm
该算法是根据每个字母出现的频率来破解
使用爬坡算法每次交换两个字母,计算得分情况,得分越高,正确结果可能性越高
通过四字组确定与文本相似情况
best score so far: -371.6099375862725 on iteration 6806 best key: ERBWAULZKDJXHFYVCGMPISTONQ plaintext: LAOBANISSOHANDSOMEIWOULDLIKETOBUYACUPOFMILKYTEAFORHIMOHBYTHEWAYTHEKEYISKINGOFSLEEP
代码
import random
import sys
from ngram_score import ngram_score
#参数初始化
text ='XEYREFKMMYZEFWMYHAKTYIXWXKJAPYRINEBIVYUHKXJNPAEUYGZKHYZRNPZATENPZAJANKMJKFLYUMXAAV'
template = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
key = {'A':'A'}
fitness = ngram_score('english_quadgrams.txt')
score = -99e9
maxn = -99e9
j = 0
while 1:
j +=1
n=len(template)
for i in range(n):
key[template[i]] = chr(ord('A')+i)
dic = text
for i in range(len(dic)):
dic = dic[:i]+key[dic[i]]+dic[i+1:]
score = fitness.score(dic)
count = 0
while count < 1000:
a = random.randint(0,25)
b = random.randint(0,25)
template[a],template[b]= template[b],template[a]
key[template[a]],key[template[b]] = key[template[b]],key[template[a]]
dic = text
for i in range(len(dic)):
dic = dic[:i]+key[dic[i]]+dic[i+1:]
sco = fitness.score(dic)
#此子密钥代替其对应的父密钥,提高明文适应度
if sco > score:
score = sco
count = 0
else:
template[a],template[b]=template[b],template[a]
key[template[a]],key[template[b]]=key[template[b]],key[template[a]]
count = count+1
if score > maxn:
maxn = score
print ('Currrent key: '+''.join(template))
print ('Iteration total:', j)
print ('Plaintext: ', dic,maxn)
sys.stdout.flush()