The Vigenère cipher in Python

The Vigenère cipher is a polyalphabetic substitution cipher system designed by Giovan Battista Bellaso and improved upon by Blaise de Vigenère. It functions very similarly to a Caesar shift cipher where a shift of lettering occurs. Unlike the Caesar shift cipher the Vigenère cipher performs different shift per character. For example the first letter may have a shift of 4 and the second letter may have a shift of 8 and so on. A key is used to define the shift value for each letter. In this script they key is a letter of the alphabet.

The program works by retrieving the index values of the characters from the key and the plain text in turn. These values are then added together and the resulting number is equal to the index value corresponding to the cipher text. For example:
We have an alphabet with each letter assigned a value a = 0 b = 1 c = 2 and so on…
If we were to have the key R and the plain text letter P we would add the values 17 for R and 15 for P. 17 + 15 = 32
If the value is greater than 26 we keep subtracting 26 until we get a number less than 26. 32 – 26 = 6.
We now look up the value 6 in the alphabet index. the value at index 6 is G.
The program simply loops through this process for each letter in the plain text till the cipher text is complete.
Feel free to use the code however you want. Let me know if you do as I would be interested in its implementation.

#-------------------------------------------------------------------------------
# Name:        Vigenere Cipher
# Purpose:
#
# Author:      James Woolley
#
# Created:     17/07/2012
# Copyright:   (c) James 2012
# Licence:     Open Source
#-------------------------------------------------------------------------------
#Creates the base Alphabet which is used for finding preceeding characters from the ciphertext.
baseAlphabet = ('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')
print ("Welcome to a Vigenere Cipher encrypter. You will first be asked to enter the plain text to be encrypted and then the key you would like to use in the encryption process. The resulting text will be the cipher text.")
plainText = raw_input("Please enter the plain text")
key = raw_input("Please enter the key")
keyList = []
keyLength = 0
while keyLength < len(plainText):
    for char in key:#Adds the users entered key into a list character by character. Also makes the key the same length as plainText
        if keyLength < len(plainText):
            keyList.append(str(char))
            keyLength = keyLength + 1
completeCipherText = [] #The variable each processed letter is appended to
cipherCharIndexValue = 0#This is the value used to temporaily store the ciphertext character during the iteration
keyIncrement = 0
for plainTextChar in plainText:#iterates through the plain text
        cipherCharIndexValue = baseAlphabet.index(keyList[keyIncrement]) + baseAlphabet.index(plainTextChar)#Adds the base alphabets index value of the key and the plain text char
        while cipherCharIndexValue > 25:
            cipherCharIndexValue = cipherCharIndexValue - 26#makes the addition value under 26 as to not go out of range of base alphabet tuple
        completeCipherText.append(baseAlphabet[cipherCharIndexValue])#appends the ciphertext character to the completeCipherText variable. The character is the index of the key + index of the plainTextChar from baseAlphabet
        keyIncrement = keyIncrement + 1#Moves onto the next key
print ''.join(completeCipherText)#Makes the result a strings for printing to the console.

5 thoughts on “The Vigenère cipher in Python

  1. Sharanya

    Hi, I am a student, I have to do a homeowork onVigenere. When the program receives P and plain text, it is to use the key to encrypt using the Vigenere coding scheme. (Use the numeric version)
    When the program receives C and ciphertext, it is to use the key to decrypt the message, using the Vigenere scheme (Again, use the numeric version).
    This is an amazing working program for encryption but I also want a program for decryption for this cipher. Can you provide me that program?

     
  2. James Woolley

    Unfortunately i don’t have a program that can decrypt Vigenere ciphers. Only this one that encrypts. I shouldn’t think the process for encrypting would be too much different that decrypting if you know the key i think you just reverse the process. There is this site : http://sharkysoft.com/misc/vigenere/ which lets you both encode and decode. Under Figure 7 http://www.mathdemos.org/mathdemos/vigenere/vigenere.html It explains how the process of decoding is just the reverse process. I hope i helped in some way 🙂

     
  3. poojitha

    Hi, i have a similar kind of home work but plain text and key can be of both uppercase and lowercase letters but cipher text must be uppercase. can you please help me with this?

     
  4. Bob

    Complete encrypt and decrypt code python 2.7:

    def menu():
    print (‘Welcome to the menu’)
    choice = (raw_input(‘Would you like to encrypt or decrypt? Enter E for encrypt or D for decrypt: ‘)).upper()
    if choice == ‘E’:
    encrypt()
    elif choice == ‘D’:
    decrypt()
    else:
    print ‘That is not a valid answer’
    menu()

    def encrypt():
    plaintext=raw_input(“Please enter the message you wish to encode: “)
    #This allows the user to enter the message they wish to encrypt.
    keyword=raw_input(“Please enter your keyword, preferably shorter than the plaintext: “)
    #This allows the user to enter a keyword.
    encoded=””
    #This creates a string for the user to input the encrypted message to.
    while len(keyword)len(plaintext):
    #This sees if the string length of the keyword is now longer than the string length of the plaintext.
    newkey=keyword[:len(plaintext)]
    #This cuts the string length of the keyword
    for c in range(len(plaintext)):
    char=ord(plaintext[c])
    temp=ord(keyword[c])
    newchar=char+temp
    if newchar>ord(“Z”):
    newchar-=25
    newnewchar=chr(newchar)
    encoded+=newnewchar
    print(encoded)

    def decrypt():
    plaintext=raw_input(“Please enter the message you wish to decode: “)
    #This allows the user to enter the message they wish to encrypt.
    keyword=raw_input(“Please enter your keyword, preferably shorter than the plaintext: “)
    #This allows the user to enter a keyword.
    encoded=””
    #This creates a string for the user to input the encrypted message to.
    while len(keyword)len(plaintext):
    #This sees if the string length of the keyword is now longer than the string length of the plaintext.
    newkey=keyword[:len(plaintext)]
    #This cuts the string length of the keyword
    for c in range(len(plaintext)):
    char=ord(plaintext[c])
    temp=ord(keyword[c])
    newchar=char-temp
    if newchar<ord("a"):
    newchar+=25
    newnewchar=chr(newchar)
    encoded+=newnewchar
    print(encoded)

    menu()

     

Leave a Reply

Your email address will not be published. Required fields are marked *