import argparse import re import vig import os def probe(key, substrings, words): key_hits = {} for x in range(ord('a'), ord('z')+1): count = 0 for substr in substrings: if re.search(vig.decrypt(key+chr(x), substr[0:len(key)+1]), words): count += 1 key_hits[key+chr(x)] = count best_val = [val for key, val in sorted( key_hits.items(), key=lambda ele: ele[1])][-1] return {key: val for key, val in key_hits.items() if val == best_val} def remove_crap_from_list(tree, max_depth, thr): best = [-x * thr for x in range(max_depth+2)] for key, val in tree.items(): if val > best[len(key)]: best[len(key)] = val import copy tmp = copy.copy(list(tree.items())) for key, val in tmp: for i in range(len(key), max_depth+1): if val < (best[i] - thr + (i-len(key))*thr*1.5): del tree[key] break def crack(substrings, words): tree = {"": 0} while tree: curr = [key for key, val in sorted( tree.items(), key=lambda ele: ele[1])][-1] if len(curr) == len(substrings[0]): return curr del tree[curr] tree.update(probe(curr, substrings, words)) remove_crap_from_list(tree, len(substrings[0]), 10) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('FILE') parser.add_argument('--keylen', type=int, metavar="INT", required=True) args = parser.parse_args() t = ''.join([x for x in open(args.FILE, "r").read().lower() if x.isalpha()]) substrings = [(t[i:i+args.keylen]) for i in range(0, len(t), args.keylen)] words = open(os.path.abspath(os.path.dirname(__file__))+"/words.txt", "r").read() print(crack(substrings, words))