题目传送门在此。
这关还是维吉尼亚密码,给了我们三个加密文本,不过没有告诉我们长度,但是频率统计还是奏效。
于是乎,首先在这里分别提交三个加密文本,可以发现最可能的长度是3或者9,3个文本都满足这一特性。
然后用程序统计频率,尝试将最高频的字母当作e来进行解密:
def decode(s, key):
ans = ''
l = len(key)
for k in xrange(len(s)):
i = k / l
j = k % l
ans += chr((ord(s[i * l + j]) - ord(key[j]) + 26) % 26 + ord('a'))
return ans
def search(base_s, deep, sec, key):
if deep == sec:
text = decode(base_s, key)
if text.find('the') >= 0:
print(text[0:20], key)
return
s = base_s[deep::sec]
d = {}
for c in s:
if c in d:
d[c] += 1
else:
d[c] = 1
ans = sorted(d.items(), key=lambda d:d[1])
low = ans[len(ans) - 1][1] - 3
for one in ans:
if one[1] >= low:
search(base_s, deep + 1, sec, key + chr((ord(one[0]) - ord('E') + 26) % 26 + ord('A')))
其中我架设解密文本中一定含有the,以尽量减少人工选择量,然后low可以根据个人感觉来设定,只有出现次数不小于low的才会被考虑当作e。
首先尝试长度为3:
>>> search(s2, 0, 3, '')
('wsaoesamfiwcpedqched', 'KTC')
('wsvoenamaiwxpeyqcced', 'KTH')
很显然不太对,然后尝试长度为9,由于比较长,只选择一部分:
('whentsumeilgotdkcges', 'KEYLECQTD')
('whentsumailgotdkcces', 'KEYLECQTH')
('whentsumlilgotdkcnes', 'KEYLECQTW')
('whentsumrilgotdkctes', 'KEYLECQTQ')
('whentspmeilgotdfcges', 'KEYLECVTD')
('whentspmailgotdfcces', 'KEYLECVTH')
('whentspmlilgotdfcnes', 'KEYLECVTW')
('whentspmrilgotdfctes', 'KEYLECVTQ')
('whenthumeilgotskcges', 'KEYLENQTD')
('whenthumailgotskcces', 'KEYLENQTH')
('whenthumlilgotskcnes', 'KEYLENQTW')
('whenthumrilgotskctes', 'KEYLENQTQ')
('whenthpmeilgotsfcges', 'KEYLENVTD')
('whenthpmailgotsfcces', 'KEYLENVTH')
('whenthpmlilgotsfcnes', 'KEYLENVTW')
('whenthpmrilgotsfctes', 'KEYLENVTQ')
('wxeyjsumeibgzjdkcgei', 'KOYAOCQTD')
('wxeyjsumaibgzjdkccei', 'KOYAOCQTH')
('wxeyjsumlibgzjdkcnei', 'KOYAOCQTW')
('wxeyjsumribgzjdkctei', 'KOYAOCQTQ')
('wxeyjspmeibgzjdfcgei', 'KOYAOCVTD')
('wxeyjspmaibgzjdfccei', 'KOYAOCVTH')
('wxeyjspmlibgzjdfcnei', 'KOYAOCVTW')
其中的whenth部分看起来比较像when the,然后看对应的key,key似乎就应该是keylength。于是解密检查,确认密钥正确。
然后用此密钥,解密即可得到下一关的password。