Python - Cipher Problem

Associate
Joined
20 Apr 2015
Posts
1
Hi,

For Computing GCSE coursework we have to code in Python a Vigenere cipher i have started to do this using code i have sourced from different places on the internet. However i am struggling to make the program work and to make it not bring up any errors.

Any help or tips would be greatly appreciated.

#This is my code

LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def getMessage():
print('Enter your message:')
return input()

def getKey():
while True:
print('Enter the key number')
return input()

def getMode():
while True:
print('Do you wish to encrypt or decrypt a message?')
mode = input().lower()
if mode in 'encrypt decrypt'.split():
return mode
else:
print('Enter either "encrypt" or "decrypt".')

def main():
# This text can be copy/pasted from http://invpy.com/vigenereCipher.py
myMessage = getMessage()
myKey = getKey()
myMode = getMode()

if myMode == 'encrypt':
translated = encryptMessage(myKey, myMessage)
elif myMode == 'decrypt':
translated = decryptMessage(myKey, myMessage)

print('%sed message:' % (myMode.title()))
print(translated)
print()

def encryptMessage(key, message):
return translateMessage(key, message, 'encrypt')


def decryptMessage(key, message):
return translateMessage(key, message, 'decrypt')


def translateMessage(key, message, mode):
translated = [] # stores the encrypted/decrypted message string

keyIndex = 0
key = key.upper()

for symbol in message: # loop through each character in message
num = LETTERS.find(symbol.upper())
if num != -1: # -1 means symbol.upper() was not found in LETTERS
if mode == 'encrypt':
num += LETTERS.find(key[keyIndex]) # add if encrypting
elif mode == 'decrypt':
num -= LETTERS.find(key[keyIndex]) # subtract if decrypting

num %= len(LETTERS) # handle the potential wrap-around

# add the encrypted/decrypted symbol to the end of translated.
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())

keyIndex += 1 # move to the next letter in the key
if keyIndex == len(key):
keyIndex = 0
else:
# The symbol was not in LETTERS, so add it to translated as is.
translated.append(symbol)

return ''.join(translated)


# If vigenereCipher.py is run (instead of imported as a module) call
# the main() function.
if __name__ == '__main__':
main()
 
Soldato
Joined
1 Mar 2003
Posts
5,508
Location
Cotham, Bristol
Interesting little problem I had to look up the cipher on wikipedia, using the same example they do in their description here is what I came up with. It assumes the message and the keyword only contain a-z lower case letters

Code:
def createVigenereSquare():
   start = ord('a')
   end = start + 26
   index = start
   sq = [''] * 256   
   for i in  range(start, end):
      row = [''] * 256
      for j in  range(start, end):
         if index > (end - 1):
            index = start
         row[j] = chr(index)
         index += 1
      sq[i] = row
      index = i + 1 
   return sq

def createKey(message, keyword):
   n = 0
   key = ""
   for i in range(0, len(message)):
      if n >= len(keyword):
         n = 0
      key += keyword[n]
      n += 1
   return key

def createCipherText(message, key):
   vsquare = createVigenereSquare()
   cipher = ""
   for i in range(0, len(key)):
      cipher += vsquare[ord(key[i])][ord(message[i])]
   return cipher

message = "attackatdawn"
keyword = "lemon"
key = createKey(message, keyword)
ciphertext = createCipherText(message, key)
print "Message: " + message
print "Keyword: " + keyword
print "Key: " + key
print "Ciphertext: " + ciphertext
 
Soldato
Joined
1 Mar 2003
Posts
5,508
Location
Cotham, Bristol
A small update

Code:
 """
In a Caesar cipher, each letter of the alphabet is shifted along some number of places; for example, in a Caesar cipher of shift 3, A would become D, B would become E, Y would become B and so on. The Vigenère cipher consists of several Caesar ciphers in sequence with different shift values.

To encrypt, a table of alphabets can be used, termed a tabula recta, Vigenère square, or Vigenère table. It consists of the alphabet written out 26 times in different rows, each alphabet shifted cyclically to the left compared to the previous alphabet, corresponding to the 26 possible Caesar ciphers. At different points in the encryption process, the cipher uses a different alphabet from one of the rows. The alphabet used at each point depends on a repeating keyword.[citation needed]

For example, suppose that the plaintext to be encrypted is:
ATTACKATDAWN
The person sending the message chooses a keyword and repeats it until it matches the length of the plaintext, for example, the keyword "LEMON":
LEMONLEMONLE
Each row starts with a key letter. The remainder of the row holds the letters A to Z (in shifted order). Although there are 26 key rows shown, you will only use as many keys (different alphabets) as there are unique letters in the key string, here just 5 keys, {L, E, M, O, N}. For successive letters of the message, we are going to take successive letters of the key string, and encipher each message letter using its corresponding key row. Choose the next letter of the key, go along that row to find the column heading that matches the message character; the letter at the intersection of [key-row, msg-col] is the enciphered letter.

For example, the first letter of the plaintext, A, is paired with L, the first letter of the key. So use row L and column A of the Vigenère square, namely L. Similarly, for the second letter of the plaintext, the second letter of the key is used; the letter at row E and column T is X. The rest of the plaintext is enciphered in a similar fashion:

Plaintext: ATTACKATDAWN 
Key: LEMONLEMONLE 
Ciphertext: LXFOPVEFRNHR 

Decryption is performed by going to the row in the table corresponding to the key, finding the position of the ciphertext letter in this row, and then using the column's label as the plaintext. For example, in row L (from LEMON), the ciphertext L appears in column A, which is the first plaintext letter. Next we go to row E (from LEMON), locate the ciphertext X which is found in column T, thus T is the second plaintext letter.

"""
class VigenereSquare:

   def __init__(self):
       self.square = self.createVigenereSquare()

   def createVigenereSquare(self):
      start = ord('a')
      end = start + 26
      index = start
      sq = [''] * 256
      for i in range(start, end):
         row = [''] * 256
         for j in range(start, end):
            if index > (end - 1):
               index = start
            row[j] = chr(index)
            index += 1
         sq[i] = row
         index = i + 1
      return sq

class CipherKey:

   def __init__(self, text, keyword):
      self.key = self.createKey(text, keyword)

   def createKey(self, text, keyword):
      n = 0
      key = ""
      for i in range(0, len(text)):
         if n >= len(keyword):
            n = 0
         key += keyword[n]
         n += 1
      return key

class VigenereCipherEncrypter:


   def createCipherText(self, message, key, vsquare):
      cipher = ""
      for i in range(0, len(key.key)):
         cipher += vsquare.square[ord(key.key[i])][ord(message[i])]
      return cipher

class VigenereCipherDecrypter:

   def decryptCipher(self, cipher, key, vsquare):
      message = ""
      for i in range(0, len(key.key)):
         index = vsquare.square[ord(key.key[i])].index(cipher[i])
         message += chr(index)
      return message


if __name__ == "__main__":
   message = input("Enter message to encrypt (a-z characters only): ")
   keyword = input("Enter the keyword: ")

   cipherkey = CipherKey(message, keyword)
   vsquare = VigenereSquare()
   vigenereencrypter = VigenereEncrypter()

   ciphertext = vigenereencrypter.createCipherText(message, cipherkey, vsquare)
   print "Encrypted message: " + ciphertext

   vigeneredecrypter = VigenereCipherDecrypter()
   decryptedmessage = vigeneredecrypter.decryptCipher(ciphertext, cipherkey, vsquare)
   print "Decrypted message: " +decryptedmessage
 
Back
Top Bottom