Python 制作Vigen&xE9;重新加密/解密跳过空白
我用Vigenére密码制作了一个基于菜单的加密工具。到目前为止,该程序加密空白,我如何才能让程序跳过空白Python 制作Vigen&xE9;重新加密/解密跳过空白,python,python-3.x,encryption,whitespace,vigenere,Python,Python 3.x,Encryption,Whitespace,Vigenere,我用Vigenére密码制作了一个基于菜单的加密工具。到目前为止,该程序加密空白,我如何才能让程序跳过空白 #creating variables to be used text_in_use = '' encrypt_key = '' decrypt_key = '' #function to encypypt input text def encrypt(plaintext, key): keyLength = len(key) keyAsIntegers = [ord(i
#creating variables to be used
text_in_use = ''
encrypt_key = ''
decrypt_key = ''
#function to encypypt input text
def encrypt(plaintext, key):
keyLength = len(key)
keyAsIntegers = [ord(i) for i in key] #create list with the ASCII value for each charachter in key
plaintextAsIntegers = [ord(i) for i in plaintext] #create list with the ASCII value for each charachter in text
encyptedtext = ''
for i in range(len(plaintextAsIntegers)): #
encryptvalue = (plaintextAsIntegers[i] + keyAsIntegers[i % keyLength]) % 26 #execute encryption or characters according to vigenere definition
encyptedtext += chr(encryptvalue + 65)
return encyptedtext #return the encyptes tex
#function to decrypt the encrypted text
def decrypt(encyptedtext, key):
keyLength = len(key)
keyAsIntegers = [ord(i) for i in key] #create list with the ASCII value for each charachter in key
encryptedTextAsIntegers = [ord(i) for i in encyptedtext] #create list with the ASCII value for each charachter in text
plaintext = ''
for i in range(len(encryptedTextAsIntegers)):
value = (encryptedTextAsIntegers[i] - keyAsIntegers[i % keyLength]) % 26 #decryption of encrypted characters
plaintext += chr(value + 65)
return plaintext #return decrypted text
#check if user input is valid
def check_value(userEntry):
while True:
try: #check if userinput is an integer
userInput = int(input(userEntry))
if userInput not in range(1,6): #check if userinput is in valid range
print("Invalid choice, valid choices are 1-5! Try again! \n")
except ValueError:
print("Invalid choice! Input can't be empty or a string! \n")
print("""1: Input text to work with
2: Print the current text
3: Encrypt the current text
4: Decrypt the current text
5: Exit""")
else:
return userInput #return valid userinput
def menu():
while True:
print("""1: Input text to work with
2: Print the current text
3: Encrypt the current text
4: Decrypt the current text
5: Exit""")
choice = check_value("Enter Choice: ")
if choice == 1: #allows user to input text for use
text_in_use = str(input("Enter Text: ")).upper()
print("Text is set to:",text_in_use,"\n")
elif choice == 2: #prints set text
print("Your text:",text_in_use,"\n")
elif choice == 3: #ask user to set encryptionkey
encrypt_key = str(input("Enter an encryptionkey: ")).upper()
text_in_use = encrypt(text_in_use, encrypt_key)
print("Your text:", text_in_use)
elif choice == 4: #ask user for decryptionkey
decrypt_key = str(input("Enter a the decryptionkey: ")).upper()
text_in_use = decrypt(text_in_use, decrypt_key)
print("Your text:", text_in_use)
elif choice == 5:
exit()
menu()
我希望程序能够像以前一样工作,但它应该跳过加密中的空白
例如:
“你好,我的人”-->加密(key=asd)-->“HWOLG MQ MSQ”
换句话说,在加密文本中应该仍然存在空格。不确定当明文为“HELLO MY MAN”且密钥为“asd”时,如何获得“HWOLG MQ MSQ”。我还有别的事要做
无论如何,可能是这样的:
def encrypt(plaintext, key):
from itertools import cycle
from string import ascii_uppercase as alphabet
offset = ord("A")
key_char = cycle(key)
encrypted_plaintext = ""
for char in plaintext:
# If the current character is any kind of whitespace...
if char.isspace():
# Append it to the final string with no changes.
encrypted_plaintext += char
else:
# The character is not whitespace, so you have to encrypt it.
char_sum = ord(char) + ord(next(key_char))
char_sum_wrapped = char_sum % len(alphabet)
encrypted_plaintext += chr(char_sum_wrapped + offset)
return encrypted_plaintext
如果当前字符是空白,只需将其附加到最后一个字符串中,而不做任何更改<如果字符串(当前字符)中的每个字符都是某种空白(空格、制表符、换行符、回车符等),则code>str.isspace返回true
我尽量避免使用索引和硬编码数字,所以我改变了一些事情。例如,在执行其他操作之前,我没有像您那样将明文和密钥中的所有字符转换为整数,而是转换循环中的字符。顺便说一句,循环也是不同的-我在明文中迭代字符,而不是对循环执行基于范围的操作,然后将I
作为当前字符的索引。其余的基本相同(除了key\u char
和itertools.cycle
内容,请阅读下面我的注释)
另一件需要注意的事情是,在这个实现中,只有当明文中的当前字符不是空白时,key\u char
迭代器才会前进-但是,您可能希望它无论如何前进。只是要记住一些事情
别担心,这似乎是这个密码想要的行为
另外,请注意,您的程序从以下几行开始:
#creating variables to be used
text_in_use = ''
encrypt_key = ''
decrypt_key = ''
它们根本不起作用,您可以安全地移除它们
编辑-更多信息:
itertools.cycle
是一个函数,给定一个iterable(如字符串或列表),它返回一个迭代器,生成该iterable中的元素。例如:
>>> from itertools import cycle
>>> char_iterator = cycle("ABC")
>>> next(char_iterator)
'A'
>>> next(char_iterator)
'B'
>>> next(char_iterator)
'C'
>>> next(char_iterator)
'A'
>>> next(char_iterator)
'B'
>>> next(char_iterator)
'C'
>>> next(char_iterator)
'A'
>>>
正如你所看到的,循环无限期地重复。出于这个原因,我选择使用itertools.cycle
替换原始代码中的keyAsIntegers[I%keyLength]
string.ascii_大写字母
只是一个由a-Z之间的所有大写字母组成的字符串。在我的代码中,我导入了ascii_大写字母
,并在同一行将其重命名为字母表
,但它们是相同的
>>> from string import ascii_uppercase as alphabet
>>> alphabet
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>>
您可以忽略空白的加密方法,或者重构代码,只对实际单词进行加密,例如使用
明文.split(“”)
获取要加密的单词列表,然后对列表中的每个项目运行加密/解密
下面是如何在加密过程中忽略空白。请注意,此实现假定通过“跳过空白”,意味着您通常仍会加密空白。空格仍然是关键,它不是完全正确的行为
def encrypt(plain_text, key):
...
for i in range(len(plaintextAsIntegers)):
if plain_text[i] == ' ':
encryptedtext += ' '
else:
encryptvalue = (plaintextAsIntegers[i] + keyAsIntegers[i % keyLength]) % 26
encyptedtext += chr(encryptvalue + 65)
解密应该是相反的过程
...
if encryptedtext[i] == ' ':
plain_text += ' ':
else:
...
这使得加密更弱,因为可以根据单词的长度猜出单词的长度。最好将所有空格(包括制表符等)作为一个字符进行加密。加密的全部目的是使密码文本看起来尽可能随机。如果你保留空间,它会更容易破裂。不管怎样,常规算法也会加密空白,所以你要么修改算法,要么单独加密每个单词。这有一些重复,但这一个的措辞很好,而其他人似乎更为糟糕的代码/附加问题/更具体的代码特定问题,并且往往没有得到回答,因此kudo对此表示支持。但是,请特别注意标题的正确性,并在发布前查看您的帖子。我已经投了赞成票,但这个问题是不正确的,您需要保留一个单独的偏移量,以指示要使用的键中的下一个字符。请修复。@MaartenBodewes很确定他们用这段代码就是这么做的,不是吗
keyAsIntegers[i%keyLength]
…问题是,即使找到空间,i
也会前进。人们通常认为维格纳不是这样运作的。密文应该是相同的,有空格或没有空格。至少在回答中应该注意到这一点,但老实说,我认为大多数学者认为目前的答案是错误的。这取决于你对“跳过”的解释tbh@MaartenBodewes更新为包含假设等,感谢您指出。很好,我绝对喜欢isspace()
和循环
。这使得代码更易于阅读,因为它解释了代码试图实现的目标。当然,对于一个可能不被期望的初学者来说:)嗨,你似乎知道你在说什么!然而,你能对代码中发生的事情发表一些评论吗?因为我是一个初学者,很难理解发生的事情,正如上面的评论所提到的:)谢谢你们的反馈。我用更多的信息更新了我的帖子。如果我能更清楚地解释什么,请告诉我。