def __init__(self): self.letCounter = LetterCounts() self.ic = { "english" : 0.065, "equiprobable" : 0.038} # ic of english language self.engIC = 0.065 # ic of perfectly random message (all letters equiprobable) self.ranIC = 0.038 self.vigenereSquare = self.constructVigenereSquare()
class VigenereCipher: def __init__(self): self.letCounter = LetterCounts() self.ic = { "english" : 0.065, "equiprobable" : 0.038} # ic of english language self.engIC = 0.065 # ic of perfectly random message (all letters equiprobable) self.ranIC = 0.038 self.vigenereSquare = self.constructVigenereSquare() ## clearMsg # # cleans up the ciphertext so that it only contains # A-Z characterws # def clearMsg(self, msg): return msg.replace(' ', '') ## Index of Coincidence (IC) # The IC of the English Language is 0.065 # The IC of a text written where all letters are # equiprobable is 0.038 # # IC is equivalent to the sum from i=1 to 26 # of c**2/n**2 where n is the length of the # string and c is the count of the letter # (corresponding letter of the alphabet) in # the message # def calcIC(self, msg): # Determine the letter counts in the message counts = self.letCounter.getCounts(msg) # Determine the squared length of the message n = len(msg)**2 # The IC (results from a summation) ic = 0 for letter,num in counts: # Since some of the counts could be 0, skip those if num == 0: continue ic += num**2/float(n) return ic ## isMonoalphabetic # # determines if the IC is closer to the English Language # IC or to the IC of text with equiprobable letter occurrence # # return: whether the IC is closer to english IC or not def isMonoalphabetic(self, ic): deltaEng = abs(self.ic["english"] - ic) deltaEqui = abs(self.ic["equiprobable"] - ic) return deltaEng > deltaEqui ## constructVigenereSquare # # The Vigenere Square is a mapping of the simple shifts performed # when encrypting a message using a Vigenere cipher keyword # # In other words, keyword 'a' shifts letters by 0 # so vigengereSquare['a']['c'] = 'C' def constructVigenereSquare(self): alphabet = list(string.ascii_uppercase) lowerbet = list(string.ascii_lowercase) vigenereSquare = {} for shift, rowLet in enumerate(lowerbet): vigenereSquare[rowLet] = {} for idx, colLet in enumerate(lowerbet): vigenereSquare[rowLet][colLet] = alphabet[(idx+shift)%len(alphabet)] return vigenereSquare ## vigenereSquareDecrypt # # c is the cipher letter (i.e. 'N') # p is the plaintext letter that the cipher letter # is expected to correspond to (i.e. 'e') # def vigenereSquareDecrypt(self, c, p='e'): for key, value in self.vigenereSquare[p].items(): if value == c: return key return None ## vigenereSquareLookup # # k is the keyword letter (i.e. 'j') # p is the plaintext letter to encrypt (shift) # c is the ciphertext letter found via table lookup # def vigenereSquareLookup(self, k, p, printTable=False): return self.vigenereSquare[k][p] def encrypt(self, msg, key, printTable=False): keyLen = len(key) encryptedMsg = "" if printTable: print " __________________________________" print "| Keyword | Plaintext | Ciphertext |" for i in range(0, len(msg), keyLen): chunk = msg[i:i+keyLen] # encrypt using the vigenere square for chunkIdx in range(0, len(chunk)): keyLet = key[chunkIdx] msgLet = chunk[chunkIdx] cipherLet = self.vigenereSquareLookup(keyLet, msgLet) if printTable: print "| %s | %s | %s | " % (keyLet, msgLet, cipherLet) encryptedMsg += cipherLet if printTable: print "|__________________________________|" return encryptedMsg ## decrypt # # Decrypts a message using the key and the Vigenere Square # # msg is the message to decrypt # key is the key used to encrypt the message # def decrypt(self, msg, key, printTable=False): keyLen = len(key) decryptedMsg = "" if printTable: print " __________________________________" print "| Keyword | Ciphertext | Plaintext |" for i in range(0, len(msg), keyLen): # slice out a chunk of the message (len <= size of key) chunk = msg[i:i+keyLen] # decrypt the chunk using the key for chunkIdx in range(0, len(chunk)): keyLet = key[chunkIdx] msgLet = chunk[chunkIdx] plainLet = self.vigenereSquareDecrypt(msgLet, keyLet) if printTable: print "| %s | %s | %s | " % (keyLet, msgLet, plainLet) decryptedMsg += plainLet if printTable: print "|__________________________________|" return decryptedMsg