Search code examples
pythonfunctionpython-3.xencryptionvigenere

Vigenère Cipher function implementation


After watching this tutorial about the Vigenere Cipher, I (hopefully) understand its basic concepts. We want to assign a key to a string, and then shift each letter in the string by the (0-based) alphabet-position value of each letter in the key. So when using bacon as the key,

Meet me in the park at eleven am
baco nb ac onb acon ba conbac on

becomes

Negh zf av huf pcfx bt gzrwep oz

As I'm writing a Vigenere Cipher from scratch, I only know that the first step is to assign the key to a string. And while I'm doing this, I want to recognize whether or not each of the characters is alpha so that I can preserve any special characters in the string (!, @, #, etc.) if there are any.

text = input("Enter some text:")

def encrypt(text):

#key = bacon
encrypted = []
baconvalue = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3, 'd':3, 'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6, 'H':7, 'h':7, 'I':8, 'i':8, 'J':9, 'j':9, 'K':10, 'k':10, 'L':11, 'l':11, 'M':12, 'm':12, 'N': 13, 'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16, 'q':16, 'R':17, 'r':17, 'S':18, 's':18, 'T':19, 't':19, 'U':20, 'u':20, 'V':21, 'v':21, 'W':22, 'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25 }


for letter in text:

#assign 'bacon' to text to get rotation value for each character
#preserve alpha characters

        if letter.isalpha():  
      
#character in string rotates x amount according to the corresponding value of char in bacon
        
            encrypted.append(letter, baconvalue)        

        else:    
    
            encrypted.append(letter)            
    
        return ''.join(encrypted)

print(encrypt(text,))

But as you can see, I don't know where to start as far as how to assign bacon to the string. Am I at least on the right track?


Solution

  • The way to index over your string with the value that the user enters as the key, is to create a variable starting_index and set it to = 0. This way, iteration will start at the first character in the string and you'll be able to generate a rotation value using the alphabet_pos dictionary that you created earlier.

    Use your rotate function to rotate the letters by the new rotation variable that you created. If the letter is found in your dictionary, the encrypt function will append this new letter and continue until you've reached the last index value in the key. Then it will join together the encrypted letters.

    alphabet_pos = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3, 'd':3,
    'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6, 'H':7, 'h':7, 'I':8, 'i':8,
    'J':9, 'j':9, 'K':10, 'k':10, 'L':11, 'l':11, 'M':12, 'm':12, 'N': 13,
    'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16, 'q':16, 'R':17, 'r':17,
    'S':18, 's':18, 'T':19, 't':19, 'U':20, 'u':20, 'V':21, 'v':21, 'W':22,
    'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25 }
    
    def alphabet_position(letter):
        alphabet_pos = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3,
    'd':3, 'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6, 'H':7, 'h':7, 'I':8,
    'i':8, 'J':9, 'j':9, 'K':10, 'k':10, 'L':11, 'l':11, 'M':12, 'm':12,
    'N': 13, 'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16, 'q':16,
    'R':17, 'r':17, 'S':18, 's':18, 'T':19, 't':19, 'U':20, 'u':20, 'V':21,
    'v':21, 'W':22, 'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25
    }
        pos = alphabet_pos[letter]
        return pos
    
    def rotate(letter, rot):
        shift = 97 if letter.islower() else 65
        return chr((ord(letter) + rot - shift) % 26 + shift)
    
    def encrypt(text, key):
        encrypted = []    
        starting_index = 0
        for letter in text:
        # if it's alphanumerical, keep it that way
        # find alphabet position
            rotation = alphabet_position(key[starting_index])
        # if it's a space or non-alphabetical character, append and move on
            if not letter in alphabet_pos:
                encrypted.append(letter)
            elif letter.isalpha():            
                encrypted.append(rotate(letter, rotation))             
    
        #if we've reached last index, reset to zero, otherwise + by 1
            if starting_index == (len(key) - 1): 
                starting_index = 0
            else: 
                starting_index += 1
    
        return ''.join(encrypted)    
    
    text = input("Enter some text:")
    key = input("Enter a key:")
    
    print(encrypt(text,key))