def naive_frequency(self): """ Executes a symbol frequency attack. Assumes the most common plaintext symbols are `e`, `a`, and `t` respectively. Example: >>> # demonstrates usage and naivette >>> from crypto.classical import AffineCipher >>> cipher = AffineCipher(9, 18) >>> ciphertext = cipher.encrypt('This is not a test') >>> attack = AffineAttack(ciphertext) >>> attack.naive_frequency() 'estdtdyzelepde' >>> # above not equal to 'thisisatest' because 't' is the most common character """ # TODO: The doctest for this function randomly failed with the plaintext 'This is a test'. # Occaisionally it would compute the (alpha, beta) pair as (20, 22), which is weird... most_common = self.frequencies.most_common(3) b1 = int_mapping(most_common[0][0]) # Pick `e` and `t` over `e` and `a` so that the matrix is invertible mod 26. b3 = int_mapping(most_common[2][0]) b = numpy.matrix([[b1], [b3]]) # Hard code the matrix inverse. The word 'naive' *is* in the function name... m_inverse = numpy.matrix([[19, 7], [3, 24]]) x = numpy.transpose(numpy.mod(m_inverse * b, 26)).tolist()[0] cipher = AffineCipher(*x) return cipher.decrypt(self.ciphertext)
def encode(string): """ Encodes an alphabetic string such that a:0, b:1, c:2, ... Example: >>> HillCipher.encode('abc') [0, 1, 2] """ return [int_mapping(c) for c in string]
def decrypt_chr(self, character): """ Decrypts a single given character by first mapping that character to a number in the range 0..25 before numerically decrypting it and mapping it back to a character. Example: >>> cipher = AffineCipher(9, 18) >>> cipher.decrypt_chr('s') 'a' """ return char_mapping(self.a_inverse * (int_mapping(character) - self.b) % self.modulus)
def encrypt_chr(self, character): """ Encrypts a single given character by first mapping that character to a number in the range 0..25 before numerically encrypting it and mapping it back to a character. Example: >>> cipher = AffineCipher(9, 18) >>> cipher.encrypt_chr('a') 's' """ return char_mapping((self.a * int_mapping(character) + self.b) % self.modulus)
def decrypt(self, cipher): """ Decrypts the given ciphertext using a Vigenere Cipher Example: >>> cipher = VigenereCipher('key') >>> cipher.decrypt('wiqceeo') 'message' """ D = (((int_mapping(c) - k) % 26) for k, c in zip(cycle(self.key), cipher)) return ''.join(char_mapping(n) for n in D)
def encrypt(self, message): """ Encrypts the given message using a Vigenere Cipher Example: >>> cipher = VigenereCipher('key') >>> cipher.encrypt('message') 'wiqceeo' """ E = (((k + int_mapping(c)) % 26) for k, c in zip(cycle(self.key), preprocess(message))) return ''.join(char_mapping(n) for n in E)
def __init__(self, key): """ Constructs a VigenereCipher from a lowercase ASCII alphabet-only string key Example: >>> cipher = VigenereCipher('thisisakey') >>> cipher = VigenereCipher('This is not a key') Traceback (most recent call last): File "<stdin>", line 1, in ? KeyError: ' ' """ self.key = [int_mapping(k) for k in key]
def str2num(s): """ Converts the given string to a numerical representation. Each letter gets mapped to a number, then each left-zero-padded number gets concatenated together to form a number representation of the given string. Example: >>> BaseRsaCipher.str2num('cat') 30120 >>> BaseRsaCipher.str2num('C A t') 30120 """ # The wrong way: # return int(''.join(str(int_mapping(c) + 1).zfill(2) for c in s)) # The right way: n = 0 for c in preprocess(s): n *= 100 n += int_mapping(c) + 1 return n