0

In school we are currently using python to create a Caeser Cipher, and a Keyword Cipher. I need help with certain parts of the Keyword cipher, mainly repeating a word to match the length of a string that has been entered, For example:

Entered String: Hello I am Jacob Key: bye Printed text: byebyebyebyeb

I'm okay at Python, but this is very hard for me. Currently this is as far as I got:

def repeat_to_length(key, Input):
return (key * ((ord(Input)/len(key))+1))[:ord(Input)]

Since It's a string I thought if I used ord It would turn it to a number, but I realised when using the ord command you can only have a single character, as I realised when I repeatedly got this error:

TypeError: ord() expected a character, but string of length 16 found

I found some code that did a keyword cipher, but I am not sure which part does the process I am trying to 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 = str(input("Please input a message using lowercase letters: "))
keyword = str(input("Please input a single word with lowercase letters: "))
key = createKey(message, keyword)
ciphertext = createCipherText(message, key)
print ("Message: " + message)
print ("Keyword: " + keyword)
print ("Key: " + key)
print ("Ciphertext: " + ciphertext)

As I've said I'm only okay at Python, so I don't really understand all the code in the above code, and I really want to be able to write most of it myself. This is my code so far:

def getMode():
      while True:
           print("Enter encrypt, e, decrypt or d")
           mode = input('Do you want to encrypt the message or decrypt? ')    #changes whether the code encrypts or decrypts message
           if mode in 'encrypt e decrypt d ENCRYPT E DECRYPT D'.split():      #defines the various inputs that are valid
                 return mode
           else:
                 print('Enter either "encrypt" or "e" or "decrypt" or "d".')       #restarts this string of code if the input the user enters is invalid

Input = input('Enter your message: ')

key = input('Enter the one word key: ')

def repeat_to_length(key, Input):
   return (key * ((ord(Input)/len(key))+1))[:ord(Input)]

encryptedKey = repeat_to_length(key, Input)

print(encryptedKey)

I know I've been pretty long winded but if anyone could provide any information on this topic, like explaining the code for the keyword cipher, or just answering my question, I would appreciate it!

AnimeDeamon

2 Answers2

2

Another possibility is to repeat the key enough times to get a string at least as long as the message, and then just grab as many characters as you need from the beginning:

>>> message='Hello I am Jacob'
>>> key='bye' 
>>> times=len(message)//len(key)+1 
>>> print((times*key)[:len(message)])
byebyebyebyebyeb

We compute times by dividing the length of the message by the length of the string, but we have to add 1, because any remainder will be dropped. times*key is just key repeated times times. This may be longer than we want, so we just take the first len(message) characters.

saulspatz
  • 5,011
  • 5
  • 36
  • 47
  • Thank you very much, this was very helpful! – AnimeDeamon Nov 03 '15 at 10:09
  • In a previous Caeser Cipher I used `If symbol.isalpha()` to make sure symbol, like apostrophes and spaces, aren't translated. Is there a way to implement it here so that after I have added the value of the keyword to the value of the original message the spaces remain without having been translated like the rest of the message? – AnimeDeamon Nov 03 '15 at 10:16
  • If I understand you right, what you did before should still work fine. – saulspatz Nov 03 '15 at 15:06
0

A simple one-liner could be

''.join(key[i % len(key)] for i in range(len(message)))

What it does, inside out:

  • We iterate over the indices of the letters in the string message
  • For each index, we take the remainder after division with the key length (using the % operator) and get the corresponding letter from the key
  • A list of these letters is constructed (using list comprehension) and joined together to form a string (the join method of an empty string)

Example:

>>> message = "Hello I am Jacob"
>>> key = "bye"
>>> print ''.join(key[i % len(key)] for i in range(len(message)))
byebyebyebyebyeb
troelsim
  • 1
  • 1