Vigenere randomized cipher with Python

To be clear before starting: I know there are similar topics, but nothing that actually offered any direct help. Also: this is a cool project; so I am not looking for anyone to order my project for me. Advice and advice is what I'm looking for. (I would go to my professor for such a thing, but he doesn't bother to check his email.)

This program is designed to take a user supplied seed, generate an integer based key, then generate a 95 x 95 matrix in which all printable ascii characters are available for encryption / decryption purposes. (Key - all alpha and capital letters)

Kicker: all cells must be randomized. See Image Below: Randomized Wignerer Matrix

I'll post my code below (Python is certainly not my single, although I'll definitely accept constructive criticism.):

import random

class Vigenere(object):

    def __init__(self, seed):
        random.seed(seed)
        #string containing all valid characters
        self.symbols= """!"#$%&'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~"""
        self.eTable = [[0 for i in range(len(self.symbols))] for i in range(len(self.symbols))]
        self.dTable = [[0 for i in range(len(self.symbols))] for i in range(len(self.symbols))]
        self.keyWord = ""
        self.message = ""
        self.ciphertext = ""
        self.keywordFromSeed(seed)

    def setMessage(self,message):
        self.message = message

    #Generate psuedorandom keyword from seed
    def keywordFromSeed(self,seed):
        Letters = []

        while seed > 0:
            Letters.insert(0,chr((seed % 100) % 26 + 65))
            seed = seed // 100
        self.keyWord = "".join(Letters)
        self.buildVigenere()

    #Contructs a 95 x 95 matrix filled randomly
    def buildVigenere(self):
        n = len(self.symbols)

        #Build the vigenere matrix
        for i in range(n):
            temp = self.symbols

            for j in range(n):
                r = random.randrange(len(temp))
                self.eTable[i][j] = temp[r]

                #This line below does not fill entire matrix. Why?
                self.dTable[j][(ord(temp[r])-32)] = chr(i+32)

                temp = temp.replace(temp[r],'')

    def encrypt(self):
        for i in range(len(self.message)):
            mi = i
            ki = i % len(self.keyWord)
            self.ciphertext = self.ciphertext + self.eRetrieve(ki,mi)

    def decrypt(self):
        for i in range(len(self.message)):
            emi = i
            ki = i % len(self.keyWord)
            char = self.dRetrieve(ki,emi)
            self.ciphertext = self.ciphertext + char
        print(self.ciphertext)

    def eRetrieve(self,ki,mi):       
        row = ord(self.message[mi]) - 32
        col = ord(self.keyWord[ki]) - 32
        print(row, col)
        return self.eTable[row][col]

    def dRetrieve(self,ki,emi):
        n = len(self.symbols)
        whichRow = ord(self.keyWord[ki]) - 32
        whichCol = ord(self.message[emi]) - 32
        return(self.dTable[whichRow][whichCol])
      

And just in case it helps, here's my main.py:

import argparse
import randomized_vigenere as rv

def main():

    #Parse parameters
    parser = argparse.ArgumentParser()
    parser.add_argument("-m", "--mode", dest="mode", default = "encrypt", help="Encrypt or Decrypt")
    parser.add_argument("-i", "--inputfile", dest="inputFile", default = "inputFile.txt", help="Input Name")
    parser.add_argument("-o", "--outputfile", dest="outputFile", default = "outputFile.txt", help="Output Name")
    parser.add_argument("-s", "--seed", dest="seed", default =7487383487438734, help="Integer seed")
    args = parser.parse_args()

    #Set seed and generate keyword
    seed = args.seed

    #Construct Matrix

    f = open(args.inputFile,'r')
    message = f.read()
    Matrix = rv.Vigenere(seed)
    Matrix.setMessage(message)

    if(args.mode == 'encrypt'):
        Matrix.encrypt()

        Matrix.setMessage(Matrix.ciphertext)
        Matrix.decrypt()
    else:
        Matrix.decrypt()

    o = open(args.outputFile,'w')
    o.write(str(Matrix.ciphertext))

if __name__ == '__main__':
    main()
      

I just used the default seed: 7487383487438734

My Plaintext: ABCdefXYZ

+3


source to share


2 answers


I was able to get it to work. I will post my version below:

main.py

import argparse
import randomized_vigenere as rv

def main():

    #Parse parameters
    parser = argparse.ArgumentParser()
    parser.add_argument("-m", "--mode", dest="mode", default = "encrypt", help="Encrypt or Decrypt")
    parser.add_argument("-i", "--inputfile", dest="inputFile", default = "inputFile.txt", help="Input Name")
    parser.add_argument("-o", "--outputfile", dest="outputFile", default = "outputFile.txt", help="Output Name")
    parser.add_argument("-s", "--seed", dest="seed", default =7487383487438734, help="Integer seed")
    args = parser.parse_args()

    #Set seed and generate keyword
    seed = args.seed

    #Construct Matrix
    f = open(args.inputFile,'r')
    message = f.read()
    Matrix = rv.Vigenere(seed)
    Matrix.setMessage(message)

    if(args.mode == 'encrypt'):
        Matrix.encrypt()
    else:
        Matrix.decrypt()

    o = open(args.outputFile,'w')
    o.write(str(Matrix.ciphertext))

    print("Seed used:",Matrix.seed)
    print("Key Generated:",Matrix.keyWord)
    print("Original Message:",Matrix.message)
    print("Decoded Message:",Matrix.ciphertext)

if __name__ == '__main__':
    main()
      

randomized_vigenere.py



(Make sure to add '<', '=' and '>' to the symbol list. For some reason they keep getting removed from this message.)

import random

class Vigenere(object):

    #Initialize Vigenere object.
        #Sets the random seed based on integer passed to the object
        #Establishes all valid symbols
        #Generates empty matrix which will contain values for encryption/decryption
        #Generates a keyword based on the integer passed to the object
    def __init__(self, seed):
        random.seed(seed)
        self.seed = seed
        self.symbols= """ !"#$%&'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"""
        self.Table = [[0 for i in range(len(self.symbols))] for i in range(len(self.symbols))]
        self.keyWord = ""
        self.message = ""
        self.ciphertext = ""
        self.keywordFromSeed(seed)

    #Sets the plaintext that will be encrypted/decrypted
    def setMessage(self,message):
        self.message = message

    #Generate psuedorandom keyword from seed
    def keywordFromSeed(self,seed):
        Letters = []

        while seed > 0:
            Letters.insert(0,chr((seed % 100) % 26 + 65))
            seed = seed // 100
        self.keyWord = "".join(Letters)
        self.buildVigenere()

    #Contructs a 95 x 95 matrix filled randomly with no repeats within same line
    def buildVigenere(self):
        random.seed(self.seed)
        temp = list(self.symbols)
        random.shuffle(temp)
        temp = ''.join(temp)

        for sym in temp:
            random.seed(self.seed)
            myList = []
            for i in range(len(temp)):
                r = random.randrange(len(temp))
                if r not in myList:
                    myList.append(r)
                else:
                    while(r in myList):
                        r = random.randrange(len(temp))
                    myList.append(r)
                while(self.Table[i][r] != 0):
                    r = (r + 1) % len(temp)
                self.Table[i][r] = sym

    #Encryption function that iterates through both the message and the keyword
        #and grabs values from Table based on the ordinal value of the current
        #character being pointed to be the iterator
    def encrypt(self):
        for i in range(len(self.message)):
            mi = i
            ki = i % len(self.keyWord)
            self.ciphertext = self.ciphertext + self.eRetrieve(ki,mi)

    def eRetrieve(self,ki,mi):       
        row = ord(self.message[mi]) - 32
        col = ord(self.keyWord[ki]) - 32
        return self.Table[row][col]

    #Decryption function that iterates through both the message and the keyword
        #and grabs values from Table based on the ordinal value of the current
        #keyWord character being pointed to be the iterator, then traversing the
        #row that corresponds to that value. While traversing that row, once there
        #is a match of the message value being searched for, take the iterator value
        #and convert it to an ascii character. This is the decrypted character
    def decrypt(self):
        self.ciphertext = ""
        for i in range(len(self.message)):
            emi = i
            ki = i % len(self.keyWord)
            self.ciphertext = self.ciphertext + self.dRetrieve(ki,emi)

    def dRetrieve(self,ki,emi):
        n = len(self.symbols)
        whichRow = ord(self.keyWord[ki]) - 32
        for i in range(n):
            if self.Table[i][whichRow] == self.message[emi]:
                decryptChar = chr(i + 32)
                return(decryptChar)
      

Thanks @ Eric-Levieil for the help

0


source


I'm going to answer this question:

#This line below does not fill entire matrix. Why?

      

I think this is your current question. If I'm not mistaken, this should be the first line of your question, not a simple comment in a function:

def buildVigenere(self):
    n = len(self.symbols)

    #Build the vigenere matrix
    for i in range(n):
        temp = self.symbols

        for j in range(n):
            r = random.randrange(len(temp))
            self.eTable[i][j] = temp[r]

            #This line below does not fill entire matrix. Why?
            self.dTable[j][(ord(temp[r])-32)] = chr(i+32)

            temp = temp.replace(temp[r],'')

      

The first thing I did was create a small standalone example:

import random

def buildVigenere():
    symbols= """!"#$%&'()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~"""

    n = len(symbols)
    eTable = [[0 for i in range(len(symbols))] for i in range(len(symbols))]
    dTable = [[0 for i in range(len(symbols))] for i in range(len(symbols))]

    #Build the vigenere matrix
    for i in range(n):
        temp = symbols

        for j in range(n):
            r = random.randrange(len(temp))
            eTable[i][j] = temp[r]
            print (r,  len(temp),  j,  len(symbols),  temp[r])
            #This line below does not fill entire matrix. Why?
            print (ord(temp[r])-32)
            dTable[j][(ord(temp[r])-32)] = chr(i+32)

            temp = temp.replace(temp[r],'')
    print dTable

buildVigenere()

      



You really need to learn how to do this if you want the answers here, and generally be a successful programmer. Finding where the problem is and being able to reproduce it in a simpler case is often the key.

Here I am getting an error:

Exception "unhandled IndexError"
list assignment index out of range

      

I am adding several print statements (see above) and I found that the error comes from the line symbols

missing < > =

.

Why don't you use chr

string to create symbols

?

And for buildVigenere

you can do a much simpler option using random.shuffle(x)

0


source







All Articles