当我删除消息和 keyL 中的所有空格时,我的 vigenere 密码只会给出一个连贯的句子。如果我将它们添加回来并尝试编写自己的代码来解释它,我会得到乱码。我 90% 确信这是由于我在尝试将 keyL 与消息对齐以使其与消息长度相同并且在相同位置具有相同空格时犯了一个错误。有人可以帮助我了解我需要添加什么来正确解释空间,而不会使当前实际正常工作的功能失调吗?
message = 'txm srom vkda gl lzlgzr qpdb? fepb ejac! ubr imn tapludwy mhfbz cza ruxzal wg zztcgcexxch!'.replace(' ', '')
key = 'friends'
def decryption(message, key):
alpha = 'abcdefghijklmnopqrstuvwxyz'
punc = '.,/?!@#%^&*":'
keyL = ''.replace(' ', '')
for i in range(len(message)):
if message[i] == ' ':
keyL += ' '
else:
keyL += key[i % len(key)]
letter_to_index = dict(zip(alpha, range(len(alpha))))
index_to_letter = dict(zip(range(len(alpha)), alpha))
decrypted = ''
i = 0
for char in message:
if char in punc:
decrypted += char
else:
number = ((letter_to_index[char]) + (letter_to_index[keyL[i]])) % len(alpha)
decrypted += (index_to_letter[number])
i += 1
return decrypted
print(decryption(message, key))
输出:
youwereabletodecodethis?nicework!youarebecomingquitetheexpertatcrytography!
预期输出:
you were able to decode this? nice work! you are becoming quite the expert at cryptography!
此循环为
keyL
生成无效值:
keyL = ''.replace(' ', '')
for i in range(len(message)):
if message[i] == ' ':
keyL += ' '
else:
keyL += key[i % len(key)]
在这个循环之后打印出
keyL
的值,你会看到:
fri ndsf iend fr endsfr endsf iend frien sfr end friendsf iends rie dsfrie ds riendsfriend
仔细看,你会发现有缺失的字母。而不是
friendsfriendsfriends
你有 frindsfiendfrends
。发生这种情况是因为您为每个循环迭代递增 i
,但只有当字符不是空格时才扩展 keyL
。
当您使用此字符串解密消息时,您会得到无效结果。
有几种方法可以解决这个问题。您现有的代码正在做很多额外的工作;你可以将其简化为:
import string
from itertools import cycle
message = "txm srom vkda gl lzlgzr qpdb? fepb ejac! ubr imn tapludwy mhfbz cza ruxzal wg zztcgcexxch!"
key = "friends"
letter_to_index = dict(zip(string.ascii_lowercase, range(len(string.ascii_lowercase))))
def decryption(message, key):
keyL = cycle(key)
decrypted = ""
for char in message.lower():
if char in string.ascii_lowercase:
decrypted += string.ascii_lowercase[
(letter_to_index[char] + letter_to_index[next(keyL)])
% len(string.ascii_lowercase)
]
else:
decrypted += char
return decrypted
print(decryption(message, key))
这里唯一真正的魔力是使用
itertools.cycle
,它为我们提供了一个迭代器,每次调用 next()
都会返回 key
中的下一个字符,当我们到达末尾时从头开始重新开始。
还要注意,我们不需要
index_to_letter
,因为我们可以访问带有数字索引的字符串。如果我们有一个像 ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
这样的字符串变量,那么 ascii_lowercase[0]
就是 a
,依此类推。