我的vigenere密码加密功能出了什么问题? [英] What's wrong with my vigenere cypher encrypt function?
问题描述
我在加密函数内部得到错误字符串索引超出范围,我不知道该如何腐烂在文本上重复.该代码仅在两个输入的长度相同时才起作用.如果可以的话,我想保持alphabetal_position和rotate_character函数相同.
I get the error string index out of range inside of the encrypt function I don't know how to get rot to repeat over text. the code only works when both inputs are the same length. i want to keep the alphabet_position and the rotate_character functions the same if i can.
alpha_lower_list = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
alpha_upper_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
"L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
def alphabet_position(letter):
if letter in alpha_upper_list:
return alpha_upper_list.index(letter)
else:
return alpha_lower_list.index(letter)
def rotate_character(char, rot):
rotated_letter = ''
if char.isalpha():
rotate = alphabet_position(char) + rot
if rotate < 26:
if char in alpha_upper_list:
rotated_letter = alpha_upper_list[rotate]
return(rotated_letter)
else:
rotated_letter = alpha_lower_list[rotate]
return(rotated_letter)
else:
if char in alpha_upper_list:
rotated_letter = alpha_upper_list[rotate % 26]
return(rotated_letter)
else:
rotated_letter = alpha_lower_list[rotate % 26]
return(rotated_letter)
else:
return(char)
def encrypt(text, rot):
lis = []
for i in range(len(text)):
lis.append(rotate_character(text[i], alphabet_position(rot[i])))
return (''.join(lis))
def main():
user_text = input("Type a message: ")
rotate_by = input("Rotate by: ")
print(encrypt(user_text, rotate_by))
if __name__ == '__main__':
main()
推荐答案
通过在程序第36行的 rot [i]
中使用迭代器,您将越界.> i 将达到您的纯文本长度,该长度可以大于键.
You are going out-of-bounds by using the iterator in rot[i]
in line 36 of your program - i
will go up to the length of your plaintext, which can be larger than the key.
尝试按键的长度执行module-div,这样就可以很好地环绕键:
Try doing a module-div by length of the key, that way you should wrap around the key nicely:
lis.append(rotate_character(text [i],Alphabet_position(rot [i%len(rot)])))
编辑您仍然对脚本返回的结果不满意,因此我进行了更深入的探讨.潜在的问题是您正在尝试实现Vigenere的某些在线工具所称的增强模式":不能保证明文和密文都不来自 [a-zA-Z]
,但是可能特殊字符",例如 [0-9]
中的元素或< space>
,<
等字符之类的字符
Edit You were still unhappy with the result your script returned, so I dug a bit deeper. The underlying problem is that you are trying to implement what some online-tools for Vigenere call "enhanced mode": neither plain- nor ciphertext are guarenteed to be from [a-zA-Z]
, but may "special characters", e.g. elements from [0-9]
or characters like <space>
, <
, etc.
如果您的脚本遇到特殊字符,它将不会旋转它,而是按原样复制它,就像在 rotate_character
的 else
分支中所做的那样;这是对的.但是,在 encrypt()
中,您为遇到的纯文本的每个符号使用了我们称为键符号"的符号.这意味着您实际上是在浪费"纯文本符号上的密钥符号,而该符号完全不会被加密(俗称旋转).
In case your script encounters a special character, it will not rotate it, but rather copy it over as-is, as done in the else
-branch of rotate_character
; this is correct. In encrypt()
, however, you consume what we shall call a "keysymbol" for every symbol of the plaintext you encounter. This means that effectively you are "wasting" a keysymbol on a plaintext symbol that will not be encrypted (vulgo rotated) at all.
一旦意识到这一点,解决方法就很明显:当我们遇到特殊字符时,将其复制到输出列表中,但不要提前键流.仅在我们确实需要使用键符号的情况下才应提前键流.
Once you realize this, the fix becomes evident: when we encounter a special character, copy it over into the output list, but don't advance the keystream. The keystream should only be advanced if we actually need to consume a keysymbol.
翻译成代码:
def encrypt(text, rot):
lis = []
keystream = 0
for i in range(len(text)):
keychar = keystream % len(rot)
if text[i].isalpha():
lis.append(rotate_character(text[i], alphabet_position(rot[keychar])))
keystream += 1
else:
lis.append(text[i])
return (''.join(lis))
这篇关于我的vigenere密码加密功能出了什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!