Search code examples
pythonencryptionasciivigenere

Vigenere Cipher, loops before 122/z


I've been coding a Vigenere Cipher, but the program loops back round before getting to the 26th letter, z. If the value is 122, instead of printing z, or maybe even a, it prinst the 96th ASCII character - `.

This is my code:

def getMode():
    while True:
       mode = input("enter encrypt, e, decrypt or d: ")
       if mode in 'encrypt e decrypt d ENCRYPT E DECRYPT D Encrypt Decrypt'.split():
           return mode
       else:
           input('Please enter encrypt or decrypt to start: ')

mode = getMode()
message = input('Enter your message: ')
for char in ' ?.,:;-!/':
    message = message.replace(char,'')
key = input('Enter the one word key: ')
times = len(message)//len(key)+1
encryptedKey = (times*key)[:len(message)]

output = []
for character in message:
    number = ord(character) - 96
    output.append(number)

outputKey = []
for character in encryptedKey:
    numberKey = ord(character) - 96
    outputKey.append(numberKey)

if mode[0] == 'd':
    outputKey = [-x for x in outputKey]

encryptedMessage = [(outputKey[i] + output[i])%26 for i in range(len(output))]
finalMessage = ''.join(chr(c + 96) for c in encryptedMessage)

print(message)
print(encryptedKey)
print(outputKey)
print(output)
print(encryptedMessage)
print('Your encrypted message is: ' + finalMessage)

Basically, If I type this:

enter encrypt, e, decrypt or d: e
Enter your message: abcdefghijklmnopqrstuvwxyz
Enter the one word key: yo
abcdefghijklmnopqrstuvwxyz
yoyoyoyoyoyoyoyoyoyoyoyoyo
[25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
[0, 17, 2, 19, 4, 21, 6, 23, 8, 25, 10, 1, 12, 3, 14, 5, 16, 7, 18, 9, 20, 11, 22, 13, 24, 15]
Your encrypted message is: `qbsdufwhyjalcnepgritkvmxo

The number that should be z, 26, is now `, and I have no clue what i've done to make that loop round early.

It's a small problem, but can really screw up the messages. Any help is appreciated - and if there is a question like this already (although I couldn't find one) please redirect me to it!

Thanks!


Solution

  • Your problem is that 26 % 26 is 0 and not 26! So instead of z (chr(96 + 26)), you get a ` (chr(96 + 0)).

    You can easily fix it but stepping by one in encrypted_message comput. :

    encryptedMessage = [(outputKey[i] + output[i] - 1)%26 + 1 for i in range(len(output))]
    

    You will then correctly get:

    [25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15, 25, 15]
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
    [26, 17, 2, 19, 4, 21, 6, 23, 8, 25, 10, 1, 12, 3, 14, 5, 16, 7, 18, 9, 20, 11, 22, 13, 24, 15]
    Your encrypted message is: zqbsdufwhyjalcnepgritkvmxo