def __init__(self, parent): """ Create a new VigenereCipherAnalyzer instance. Args: parent: a class that provides an interafce to CryptographyStudio """ super().__init__(parent) self._cipher = VigenereCipher(parent) self._widget.show_all() key_path = path.join(self.GLADE_LOCATION, "resources", self.KEY_GLADE) with open(key_path, "r") as fp: self._key_selector_buffer = fp.read() ngram_loader = NGramLoader() ngram_loader.load("hr.json") self._letter_freqs = ngram_loader.get_ngrams(1) self._update_key_length()
class VigenereCipherAnalyzer(WidgetController, CipherAnalyzer): GLADE_LOCATION = path.dirname(__file__) KEY_GLADE = "key_selector.glade" TRY_BUTTON_ID = "try_button" KEY_LENGTH_ENTRY_ID = "key_length_entry" KEY_SELECTOR_ID = "key_selector" KEY_SELECTOR_BOX_ID = "key_selector_box" KEY_SELECTOR_CI_ID = "ci_field" KEY_SELECTOR_MCI_ID = "mic_store" KEY_SELECTOR_MCI_VIEW = "mic_view" CINDEX_FIELD_ID = "coincidency_index_field" LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" def __init__(self, parent): """ Create a new VigenereCipherAnalyzer instance. Args: parent: a class that provides an interafce to CryptographyStudio """ super().__init__(parent) self._cipher = VigenereCipher(parent) self._widget.show_all() key_path = path.join(self.GLADE_LOCATION, "resources", self.KEY_GLADE) with open(key_path, "r") as fp: self._key_selector_buffer = fp.read() ngram_loader = NGramLoader() ngram_loader.load("hr.json") self._letter_freqs = ngram_loader.get_ngrams(1) self._update_key_length() def _build_gui(self): """ Build the widget UI of this WidgetController. """ super()._build_gui() def _load_gui_objects(self): """ Save references to required objects defined in the .glade file. """ super()._load_gui_objects() self._try_button = self._builder.get_object(self.TRY_BUTTON_ID) self._key_length_entry = \ self._builder.get_object(self.KEY_LENGTH_ENTRY_ID) self._key_selector = \ self._cindex_field = self._builder.get_object(self.CINDEX_FIELD_ID) self._key_selector = self._builder.get_object(self.KEY_SELECTOR_ID) def _connect_handlers(self): """ Connect signals with their handler methods. """ super()._connect_handlers() self._try_button.connect("clicked", self._try_key) self._key_length_entry.connect("value-changed", self._update_key_length) def _update_key_length(self, *args): ciphertext = self._parent.get_ciphertext() m = int(self._key_length_entry.get_text()) self._key_length = m self._create_key_selectors() freq = [{} for _ in range(m)] ttl = [0] * m filtered = filter(lambda x: x in self.LETTERS, ciphertext.upper()) avg = 0 for i, c in enumerate("".join(filtered)): ttl[i % m] += 1 if c in freq[i % m]: freq[i % m][c] += 1 else: freq[i % m][c] = 1 for i, cs in enumerate(self._cis): ci = 0; for value in freq[i].values(): ci += value * (value - 1) if ttl[i] > 1: ci /= ttl[i] * (ttl[i] - 1) else: ci = 0 avg += ci cs.set_text(str(ci)[:5]) self._cindex_field.set_text(str(avg/m)[:5]) def _create_key_selectors(self): count = self._key_length for child in self._key_selector.get_children(): child.destroy() selector_data = [self._create_key_selector() for i in range(count)] boxes, cis, mcis, self._mci_views = zip(*selector_data) self._cis, self._mcis = cis, mcis for box in boxes: self._key_selector.pack_start(box, False, False, 5) for i in range(len(mcis)): self._update_mci(i) def _update_mci(self, mci_id): ciphertext = self._parent.get_ciphertext() filtered = "".join(x for x in ciphertext.upper() if x in self.LETTERS) def mv(char, inc): return chr((ord(char) - ord('A') + inc) % 26 + ord('A')) for ind in range(len(self.LETTERS)): freq = {} ttl = 0 for i in range(mci_id, len(filtered), self._key_length): fi = filtered[i] if fi in freq: freq[fi] += 1 else: freq[fi] = 1 ttl += 1 mci = 0 for l, f in self._letter_freqs.items(): mci += f * freq.get(mv(l, ind), 0) if ttl > 0: mci /= ttl else: mci = 0 self._mcis[mci_id].append([ chr(ord('A') + ind), mci, int(mci * 1000)]) self._mcis[mci_id].set_sort_column_id(1, Gtk.SortType.DESCENDING) def _create_key_selector(self): builder = Gtk.Builder.new_from_string(self._key_selector_buffer, -1) return ( builder.get_object(self.KEY_SELECTOR_BOX_ID), builder.get_object(self.KEY_SELECTOR_CI_ID), builder.get_object(self.KEY_SELECTOR_MCI_ID), builder.get_object(self.KEY_SELECTOR_MCI_VIEW) ) def _get_key(self): key = '' for mci, mci_view in zip(self._mcis, self._mci_views): path, column = mci_view.get_cursor() if not path: path = Gtk.TreePath.new_first() mci_view.set_cursor(path) key += mci.get(mci.get_iter(path), 0)[0] return key def _try_key(self, *args): """ A handler method that trys to decrypt the text in the parents ciphertext view. Args: *args: arguments passed from the signal """ key = self._get_key() ciphertext = self._parent.get_ciphertext() self._parent.set_plaintext(self._cipher.decrypt(ciphertext, key))