0

This is what I have to do:

Write a script in Python that is an implementation of a version of the Vigenere cipher for English text. Your script should distinguish lowercase and uppercase letters (i.e., the encryption key and the plaintext are allowed to be composed of lowercase and uppercase letters but the ciphertext should be uppercase). In addition to letters, there will be four other characters in the plain text: comma (26), dot (27), dash (28), underscore (29) changing the encryption function to be under mod 30.

Your script should read from standard input and write to standard output. It should prompt the user for the encryption key of size k. The key is not allowed to be repeated as in the standard Vigenere cipher. Instead, we will follow a block cipher-based idea. Basically, the plaintext and ciphertext will have blocks of size k which is same as the key size. If the key length is shorter than the plaintext, the ciphertext of block size k of the previous block is concatenated to the key. Here is an example when the keyword is ”Carbondale” with k = 10:

Plaintext :  SIU_CS-Department_is_the_best
 Key       :  CarbondaleUIHAQBBDPTUZ,MUOUCX
 Ciphertext:  UIHAQBBDPTUZ,MUOUCXHTODQTPYUM

So, I want to know how to tackle the part of the extra characters "," "." "/" "_". This is the function that is making the encryption:

a = len(key)

b = len(text)

while (len(key1) <= len(text1)):

    for i in range(0,a):
        num1 = ord(text1[i+var])%97
        num2 = ord(key1[i+var])%97
        num3 = num1+num2
        if (num3 > 25):
            encr.append(num3%25)
        else:
            encr.append(num3)
        i + 1

    for i in range(0,a):
        encr1.append(chr(encr[i+var]+97))
        i + 1

    for i in range(0,a):
        key1.append(encr1[i+var])
        i + 1
    var = var + a
halfer
  • 19,824
  • 17
  • 99
  • 186
Marcos Guimaraes
  • 1,243
  • 4
  • 27
  • 50
  • Is your code even working for letters ? I don't understand it's logic at all. Also, giving name and explanation for constants such as 97 makes code more readable. – hivert Feb 01 '14 at 09:31

1 Answers1

0

You code currently has the following problems (I am assuming that var = 0, encr = [], encr1 = [], key1 = list(key) and text1 = list(text) happen before the code you have posted):

  1. Your while loop will never start if the key is longer than the plaintext, and never end otherwise, as you never shorten text1 (and doing so would break your indexing);
  2. You don't need to manually increment the counter in a for loop (and if you wanted to, i + 1 without assignment effectively does nothing, you need i += 1);
  3. When using mod (%), you don't need to check if e.g. num3 < 25; and
  4. If you get around to including them, note that the extra characters you list aren't the same as those specified ("/" != "-").

Rather than using ord and chr, I would build my own alphabet to cycle over, e.g.

from string import ascii_uppercase

alphabet = list(ascii_uppercase) + [",", ".", "-", "_"]

You might find this implementation of the "standard" Vigenère helpful:

from itertools import cycle

def vigenere(plain, key, alphabet):
    for p, k in zip(plain, cycle(key)):
        index = alphabet.index(p) + alphabet.index(k)
        yield alphabet[index % len(alphabet)]

Here is some pseudo code for your modified implementation:

convert all text (plain, key) to upper case
create a list to hold output
split plain into blocks of length len(key)
for each block in plain:
    if it's the first block, use key to encode
    otherwise, use the last block of encoded text in output 
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • Hi, thank you! I found some implementations of the standard Vigenere, but I did not understand how this alphabet works. – Marcos Guimaraes Feb 01 '14 at 17:48
  • I forgot to mention that before the while I made a function that check the size of the text and the size of the key, if the length of the the key is longer than the the plaintext I add an invalid character '!' to make both in the same size. I use this if: if (num3 > 25): encr.append(num3%26) To make sure that if the sum of two indexes is greater than 25 the alphabet will "start again". – Marcos Guimaraes Feb 01 '14 at 17:56
  • What don't you understand about the alphabet? Have you printed it to see what it looks like? `num3 % 25` will keep it in the right range, even if it's there already; no need to check if it's too large first. – jonrsharpe Feb 01 '14 at 18:01
  • I did not understand this code =[ from string import ascii_uppercase alphabet = list(ascii_uppercase) + [",", ".", "-", "_"] from itertools import cycle def vigenere(plain, key, alphabet): for p, k in zip(plain, cycle(key)): index = alphabet.index(p) + alphabet.index(k) yield alphabet[index % len(alphabet)] – Marcos Guimaraes Feb 01 '14 at 19:59
  • That is all the actual code I posted! I suggest you read the docs for [`string`](http://docs.python.org/2/library/string.html), [`zip`](http://docs.python.org/2/library/functions.html#zip) and [`itertools`](http://docs.python.org/2/library/itertools.html), add in plenty of `print`s and see what it is doing. – jonrsharpe Feb 01 '14 at 23:45
  • Yes, I'm talking about the code you posted. I did not understand it. – Marcos Guimaraes Feb 02 '14 at 03:59
  • 1
    Then you should split it into smaller pieces and try them in the interpreter, read the documentation links I just provided to see what the external functions do and, above all (and as I have already suggested) `print` things out to see what they are. – jonrsharpe Feb 02 '14 at 08:47