class TestLongWord(unittest.TestCase): def setUp(self): self.cipher = Transposition() self.cracker = LongWordAttack() self.open_text = normalize_text("jajasynpoklopurozzuresndosilenstvivodarnusrovnamsezemijmenemmistrukanvodstvijamatkuvlastnivsakkdovizdaprokouknutoumelnikolivjakpribuznismrtlidemzvodarnysmrtivrchnizradkynijenslavumistrumzcistirnytedvidisotcecozzenstinytveuzralouzjetotadybratretyslezlzradcumdozadkujensedobrepodivejcostvojijimkouprovedlimusimedrzetpospoluatuznenimarnesnazenivejmenusatanarozpoutejmepeklouzsevmychpredstavachrodisedevyjevykrasnemodrenadrzecimtakrychlecernajinenitonahodouodpadnivodamrtverybynahazimedovodarenskychobjektuuznehodlamdalnaslouchattemvodarenskymblabolumsedekrysysezerouzbytkyvodarenskychkonstrukcipredpovidamvecnouskazuvodarenskemafiitakjakodavnopredcasemjsmesvatouchatrutopilystejnykonecpripravimepodvodnikumzvodarnynelzeveritnikomukdomatlamuplnoucistotyvsechnytyhlebestiecekavodazestokysmrtlidemzvodarnysmrtivrchnizradkynijenslavumistrumzcistirnyzevsechstrannavodarnusilaspinyutocizhorastavbydrtizeleznemepoklopydokristalovevodytecoucistirenskesplaskysabotaztospachanavejmenusedepravdy") def test_cs_keylen4(self): self._help_test_method("pass") def test_cs_keylen7(self): self._help_test_method("hfewqjn") def test_cs_keylen10(self): self._help_test_method("fhwtudxnbs") def _help_test_method(self, key): key = self.cipher._repair_key(key) cipher_text = self.cipher.encrypt(self.open_text, key) langmodel = LangModel(get_lang_path('cs')) langmodel.get_words = self.get_words cracked_key = self.cracker.crack(cipher_text, LanguageStats(langmodel)) self.assertEqual(cracked_key, key) def get_words(self, length): words = { 4: ['ucis', 'vody', 'ahoj', 'burt', 'test', 'fail'], 7: ['poklopu', 'asdfghj', 'poklopy'], 10: ['kristalove'] } return words.get(length, [])
def test_decrypt(self): cipher = Transposition() open_text = normalize_text("Python is a general-purpose, interpreted high-level programming language") key = "password" cipher_text = cipher.encrypt(open_text, key) decrypted_text = cipher.decrypt(cipher_text, key) expected = open_text + "xx" self.assertEqual(decrypted_text, expected)
class LongWordAttack(object): """Cryptanalysis method for transposition cipher""" def __init__(self): super(LongWordAttack, self).__init__() self.max_keylen = 15 self.transposition = Transposition() def crack(self, cipher_text, langstats): key_text_pair = lambda key: ( key, self.transposition.decrypt(cipher_text, key)) key_text = (key_text_pair(key) for key in self._get_possible_keys(cipher_text, langstats)) return langstats.most_meaningful(key_text) def _get_possible_keys(self, cipher_text, langstats): reshuffle_text = self.transposition._partition_text_decrypt for keylen in self._key_lengths(cipher_text): all_words = langstats.get_words(keylen) for cipher_word in reshuffle_text(cipher_text, len(cipher_text) / keylen): cipher_counter = Counter(cipher_word) for real_word in all_words: if Counter(real_word) == cipher_counter: for key in self._get_valid_keys( cipher_word, real_word): yield key def _get_valid_keys(self, cipher_word, real_word): for perm in self._get_perms(cipher_word, 0, [], self.get_positions(real_word)): yield "".join(chr(x + ord('a')) for x in perm) def _get_perms(self, word, currPos, visited, positions): if currPos == len(word): yield visited else: c = word[currPos] for free in positions[c] - set(visited): for vis in self._get_perms(word, currPos + 1, visited + [free], positions): yield vis def get_positions(self, word): pos = {} for i, char in enumerate(word): if char in pos: pos[char].add(i) else: pos[char] = {i} return pos def _key_lengths(self, cipher_text): ltext = len(cipher_text) return (i for i in range(2, self.max_keylen + 1) if ltext % i == 0)
class LongWordAttack(object): """Cryptanalysis method for transposition cipher""" def __init__(self): super(LongWordAttack, self).__init__() self.max_keylen = 15 self.transposition = Transposition() def crack(self, cipher_text, langstats): key_text_pair = lambda key: (key, self.transposition.decrypt(cipher_text, key)) key_text = (key_text_pair(key) for key in self._get_possible_keys(cipher_text, langstats)) return langstats.most_meaningful(key_text) def _get_possible_keys(self, cipher_text, langstats): reshuffle_text = self.transposition._partition_text_decrypt for keylen in self._key_lengths(cipher_text): all_words = langstats.get_words(keylen) for cipher_word in reshuffle_text(cipher_text, len(cipher_text) / keylen): cipher_counter = Counter(cipher_word) for real_word in all_words: if Counter(real_word) == cipher_counter: for key in self._get_valid_keys(cipher_word, real_word): yield key def _get_valid_keys(self, cipher_word, real_word): for perm in self._get_perms(cipher_word, 0, [], self.get_positions(real_word)): yield "".join(chr(x + ord('a')) for x in perm) def _get_perms(self, word, currPos, visited, positions): if currPos == len(word): yield visited else: c = word[currPos] for free in positions[c] - set(visited): for vis in self._get_perms(word, currPos + 1, visited + [free], positions): yield vis def get_positions(self, word): pos = {} for i, char in enumerate(word): if char in pos: pos[char].add(i) else: pos[char] = {i} return pos def _key_lengths(self, cipher_text): ltext = len(cipher_text) return (i for i in range(2, self.max_keylen + 1) if ltext % i == 0)
def setUp(self): self.cipher = Transposition() self.cracker = LongWordAttack() self.open_text = normalize_text("jajasynpoklopurozzuresndosilenstvivodarnusrovnamsezemijmenemmistrukanvodstvijamatkuvlastnivsakkdovizdaprokouknutoumelnikolivjakpribuznismrtlidemzvodarnysmrtivrchnizradkynijenslavumistrumzcistirnytedvidisotcecozzenstinytveuzralouzjetotadybratretyslezlzradcumdozadkujensedobrepodivejcostvojijimkouprovedlimusimedrzetpospoluatuznenimarnesnazenivejmenusatanarozpoutejmepeklouzsevmychpredstavachrodisedevyjevykrasnemodrenadrzecimtakrychlecernajinenitonahodouodpadnivodamrtverybynahazimedovodarenskychobjektuuznehodlamdalnaslouchattemvodarenskymblabolumsedekrysysezerouzbytkyvodarenskychkonstrukcipredpovidamvecnouskazuvodarenskemafiitakjakodavnopredcasemjsmesvatouchatrutopilystejnykonecpripravimepodvodnikumzvodarnynelzeveritnikomukdomatlamuplnoucistotyvsechnytyhlebestiecekavodazestokysmrtlidemzvodarnysmrtivrchnizradkynijenslavumistrumzcistirnyzevsechstrannavodarnusilaspinyutocizhorastavbydrtizeleznemepoklopydokristalovevodytecoucistirenskesplaskysabotaztospachanavejmenusedepravdy")
def __init__(self): super(LongWordAttack, self).__init__() self.max_keylen = 15 self.transposition = Transposition()
def test_encrypt(self): cipher = Transposition() open_text = normalize_text("Python is a general-purpose, interpreted high-level programming language") cipher_text = cipher.encrypt(open_text, "password") expected = "hnpripiapapnevannrsrhogeiaeelglxsliteraxterehlmuoeopgrngygutdemg" self.assertEqual(cipher_text, expected)