制作Vigenére加密/解密跳过空白

问题描述 投票:2回答:2

我已经使用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) 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()

我希望程序像现在一样工作,但是它应该跳过加密中的空格。

例如:

"HELLO MY MAN" --> encryption(key = asd) --> "HWOLG MQ MSQ"

换句话说,在加密的文本中空格仍应存在。

python python-3.x encryption whitespace vigenere
2个回答
1
投票

当明文为“ 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

如果当前字符是空格,则将其附加到最终字符串,而无需进行任何更改。如果字符串(当前字符)中的每个字符都是某种空格(空格,制表符,换行符,回车等),则str.isspace返回true。

我尽量避免使用索引和硬编码数字,因此我做了一些更改。例如,我没有像您一样在执行其他任何操作之前将纯文本和键中的所有字符都转换为整数,而只是在循环中转换了字符。顺便说一句,循环也有所不同-我遍历明文中的字符,而不是进行基于范围的for循环,然后将i视为当前字符的索引。其余基本相同(key_charitertools.cycle内容除外,请阅读下面的注释)。

[另外要注意的是,在此实现中,key_char迭代器仅在明文中的当前字符不是空格的情况下才前进-但是,无论如何,您都可能希望其前进。只是要记住一点。

此外,请注意,您的程序以以下几行开头:

#creating variables to be used
text_in_use = ''
encrypt_key = ''
decrypt_key = ''

它们根本没有贡献,您可以放心地删除它们。

编辑-一些更多信息:

itertools.cycle是一个函数,给定一个可迭代的函数(如字符串或列表),它返回一个迭代器,该迭代器产生该可迭代的元素。例如:

>>> 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_uppercase只是一个字符串,由A-Z之间的所有大写字母组成。在我的代码中,我导入了ascii_uppercase,并在同一行中将其重命名为alphabet,但它们是相同的。

>>> from string import ascii_uppercase as alphabet
>>> alphabet
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> 

0
投票

您可以忽略空格的加密方法,也可以重构代码以仅对实际单词运行加密,例如,使用plaintext.split(' ')获取要加密的单词列表,然后对其中的每个项目运行加密/解密名单。

© www.soinside.com 2019 - 2024. All rights reserved.