我构建了一个Vigenere密码功能,该功能运行得很好,除了它没有通过我需要通过的编码测试之外。
这是由于我使用的是序数值,我认为测试希望我使用的功能只是旋转一个字符串字母。
我已经解决了处理非字母字符的问题,并使它可以同时使用大写和小写字符。但是,如果键具有大写或小写字符的任何变体,即键是小写而纯文本是大写,则似乎分崩离析。
def encrypt(text, key):
cipher_text = []
key = list(key)
if len(text) == len(key):
return(key)
else:
for i in range(len(text) -
len(key)):
key.append(key[i % len(key)])
for i in range(len(text)):
a = text[i]
if a.isalpha() and a.islower():
x = ((ord(text[i]) + ord(key[i])-97) % 26 + 97)
cipher_text.append(chr(x))
elif a.isalpha() and a.isupper():
x = ((ord(text[i]) + ord(key[i])-65) % 26 + 65)
cipher_text.append(chr(x))
else:
cipher_text.append(a)
return("" . join(cipher_text))
def main():
mess = input(str("What is message?"))
key = input("What is key?")
print(encrypt(mess, key))
if __name__ == '__main__':
main()
对于vigenere.encrypt('BaRFoo','BaZ')
You should have returned this:
'CaQGon'
But you actually returned this:
'PtDTha'
答案 0 :(得分:1)
从您的单个示例来看,密钥似乎不区分大小写:
def encrypt_letter(c, k):
if c.isupper():
base = ord('A')
else:
base = ord('a')
return chr((ord(c) - base + ord(k) - ord('a')) % 26 + base)
def encrypt(text, key):
key = key.lower()
return "".join([encrypt_letter(text[i], key[i % len(key)]) for i in range(len(text))])
def main():
print(encrypt('BaRFoo', 'BaZ'))
if __name__ == '__main__':
main()
答案 1 :(得分:0)
首先,我不使用python编程,所以请原谅我的表格。但是,我在在线编译器中测试了所有内容。
在回答您的问题之前,我不确定这一部分:
if len(text) == len(key):
return(key)
else:
for i in range(len(text) -
len(key)):
key.append(key[i % len(key)])
我读为“如果密钥的长度与明文的长度相同,则密钥为密文”,这显然是不正确的,除非密钥为“ aaaaaaaaa ...”。我希望这样的事情:
if len(text) > len(key):
for i in range(len(text) -
len(key)):
key.append(key[i % len(key)])
# else:
# I don't care - the key is long enough
根据Kfir Dadosh的回答,我还要指出,您实际上不需要此步骤,因此不妨直接以key[i % len(key)]
的身份访问密钥。
关于您所提到的问题。您只需检查明文(消息)是小写还是大写,然后根据以下内容更改键(将其称为 normalization -将字母转换为0-25范围内的数字以表示其在字母表中的位置的行为)那个。
if a.isalpha() and a.islower():
x = ((ord(text[i]) + ord(key[i])-97) % 26 + 97)
Here you take raw ^ ^
ascii value instead of | |
normalized (0-25) number |
|
Here you normalize the key according to the
message case
在此之后,您会遇到一些麻烦的事情,因此,如果您了解并想自己解决问题,请在这里停止阅读。
我建议将规范化和加密步骤分开,以免造成混淆。让我们先去除特殊字符,再去除最后的特殊字符,因为它很容易做到,我们只需要担心字母:
if not (text[i].isalpha()):
cipher_text.append(text[i])
continue; # done with this symbol - skip to the next one
然后借助内置方法将字母标准化。让我们将变量p用于纯文本,将k用于密钥,将c用于密文(后文):
p = ord(text[i].lower()) - ord('a') # converts to lowercase, then to number
k = ord(key[i].lower()) - ord('a') # both key AND plaintext
我用ord('a')代替了我以前习惯的65,并发现它更清晰,但这是偏好和语言传统(我不习惯)的问题。
然后进行加密步骤:
c = (p + k) % 26;
现在恢复大写。我们在变量p和k中销毁了它,但是我们仍然保留其源数组text []的值完整。我们可以使用它来恢复大写(假设大小写应该从纯文本继承):
if (text[i].islower()):
cipher_text.append(chr(c + ord('a')))
elif (text[i].isupper()):
cipher_text.append(chr(c + ord('A')))
这完成了主循环。随时对其进行修改,使其更加符合python。
for i in range(len(text)):
if not (text[i].isalpha()):
cipher_text.append(text[i])
continue;
p = ord(text[i].lower()) - ord('a')
k = ord(key[i].lower()) - ord('a')
# k = ord(key[i % len(key)].lower()) - ord('a')
# if you skipped the key lengthening process
c = (p + k) % 26;
if (text[i].islower()):
cipher_text.append(chr(c + ord('a')))
elif (text[i].isupper()):
cipher_text.append(chr(c + ord('A')))
else:
# not sure if this can happen in python, but if it does, we're probably
# in trouble
# otherwise it might as well be merged with the elif above
return("" . join(cipher_text))