You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.6 KiB
Python

from random import randint as rand
from math import log10
class Scoring:
floor = 0
def __init__(self):
self.trigrams = {}
# read trigrams from file
with open(os.path.dirname(os.path.realpath(__file__)) + '/english_trigrams.txt', 'r') as trigram_file:
for line in trigram_file:
trigram, score = line.split(' ')
self.trigrams[trigram.lower()] = int(score)
score_sum = sum(self.trigrams.values())
self.floor = log10(0.1 / score_sum)
for i in list(self.trigrams.keys()):
self.trigrams[i] = log10(float(self.trigrams[i]) / score_sum)
pass
def get_score(self, text):
score = 0
for k in range(len(text) - 3):
trigram = text[k:k + 3]
if trigram in self.trigrams:
score += self.trigrams[trigram]
else:
score += self.floor
return score
def randomize_key(key):
a_index = rand(0, 25)
b_index = rand(0, 25)
a = key[a_index]
b = key[b_index]
key = key[:a_index] + b + key[a_index + 1:]
key = key[:b_index] + a + key[b_index + 1:]
return key
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('FILE')
args = parser.parse_args()
t = ''.join([x for x in open(args.FILE, "r").read().lower() if x.isalpha()])
import os
words = open(os.path.abspath(os.path.dirname(__file__))+"/common.txt", "r").read().split('\n')
occurance_string = 'etaoinsrhdlucmfywgpbvkxqjz'
occur_count = {chr(x+0x61): 0 for x in range(26)}
for char in t:
occur_count[char]+=1
mapping = {}
sorted_occur = sorted(occur_count, key=occur_count.__getitem__, reverse=True)
for i in range(26):
mapping[occurance_string[i]]=sorted_occur[i]
key = ''.join([x for _, x in sorted(mapping.items())])
import re
import mono
best_score = -10000
best_key = key
scoring = Scoring()
trys = 0
while trys < 20000:
score = 0
tmp = randomize_key(key)
plain = mono.mono_decrypt(t, tmp)
#for word in words:
# search_res = re.search(word, plain, re.IGNORECASE)
# if search_res:
# score += len(word)
score = scoring.get_score(plain)
if score > best_score:
trys = 0
best_score = score
best_key = key
key=tmp
print(best_score)
else:
trys+=1
print(best_key)
print()
print(mono.mono_decrypt(t, best_key))