-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCryptanalysis.py
More file actions
111 lines (84 loc) · 4.4 KB
/
Copy pathCryptanalysis.py
File metadata and controls
111 lines (84 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
def calculate_letter_frequencies(text):
frequencies = {}
letters_count = 0
# we are calculating the number of occurrence for each letter.
for letter in text:
if letter.isalpha():
if frequencies.get(letter, None):
frequencies[letter] += 1
else:
frequencies[letter] = 1
letters_count += 1
for letter, count in frequencies.items():
frequencies[letter] = count / letters_count
return dict(sorted(frequencies.items(), key=lambda item: item[1], reverse=True))
def calculate_n_gram_frequencies(cipher_text: str, n_gram_length: int = 2):
n_gram_frequencies = {}
n_grams_count = 0
for i in range(len(cipher_text) - n_gram_length - 1):
n_gram = cipher_text[i:i + n_gram_length]
if n_gram.isalpha() and len(n_gram) == n_gram_length:
if n_gram in n_gram_frequencies:
n_gram_frequencies[n_gram] += 1
else:
n_gram_frequencies[n_gram] = 1
n_grams_count += 1
for letter, count in n_gram_frequencies.items():
n_gram_frequencies[letter] = count / n_grams_count
# Sort the dictionary
n_gram_frequencies = dict(sorted(n_gram_frequencies.items(), key=lambda item: item[1], reverse=True))
top_10 = dict(list(n_gram_frequencies.items())[:10])
return top_10
def calculate_doubles_frequencies(cipher_text: str):
#Finding all the double letter combinations.
doubles_frequencies = {}
doubles_count = 0
for i in range(len(cipher_text) - 1):
double = cipher_text[i:i + 2]
if double.isalpha() and double[0] == double[1]:
if double in doubles_frequencies:
doubles_frequencies[double] += 1
else:
doubles_frequencies[double] = 1
doubles_count += 1
for double, count in doubles_frequencies.items():
doubles_frequencies[double] = count / doubles_count
return dict(sorted(doubles_frequencies.items(), key=lambda item: item[1], reverse=True))
def main():
#main function
class Theme:
GREEN = "\033[92m"
DARKCYAN = "\033[36m"
BOLD = "\033[1m"
END = "\033[0m"
print("********************************************************************************\n")
print(Theme.GREEN+ Theme.BOLD +" Welcome to the Frequency Analysis program\n" + Theme.END)
print(Theme.DARKCYAN+"This program lets you obtain the frequency of each letter \n in the Monoalphabetic cipher text file and prints the \n results in the console.\n"+Theme.END)
print("********************************************************************************")
# Reading the cipher text from text file
with open('Aleem S.txt', 'r', encoding='UTF-8') as file:
cipher_text = file.read()
# Performing letter frequency analysis
letter_frequencies = calculate_letter_frequencies(cipher_text)
print(Theme.GREEN+"\nLetter frequencies:\n"+Theme.END)
for letter, frequency in letter_frequencies.items():
print(f'{letter} = {round(frequency * 100, 2)}%')
# Performing letter-combination frequency analysis in different combinations
two_letters_combinations_frequencies = calculate_n_gram_frequencies(cipher_text, n_gram_length=2)
three_letters_combinations_frequencies = calculate_n_gram_frequencies(cipher_text, n_gram_length=3)
double_letters_combinations_frequencies = calculate_doubles_frequencies(cipher_text)
four_letters_combinations_frequencies = calculate_n_gram_frequencies(cipher_text, n_gram_length=4)
print(Theme.GREEN+"\nTwo letters combinations frequencies:\n"+Theme.END)
for letter, frequency in two_letters_combinations_frequencies.items():
print(f'{letter} = {round(frequency * 100, 2)}%')
print(Theme.GREEN+"\n Three letters combinations frequencies:\n"+Theme.END)
for letter, frequency in three_letters_combinations_frequencies.items():
print(f'{letter} = {round(frequency * 100, 2)}%')
print(Theme.GREEN+"\nDouble letters combinations frequencies:\n"+Theme.END)
for double, frequency in double_letters_combinations_frequencies.items():
print(f'{double} = {round(frequency * 100, 2)}%')
print(Theme.GREEN+"\nFour letters combinations frequencies:\n"+Theme.END)
for letter, frequency in four_letters_combinations_frequencies.items():
print(f'{letter} = {round(frequency * 100, 2)}%')
if __name__ == '__main__':
main()