Skip to content

Commit 48d23df

Browse files
committed
feat: frequency analysis with the bruteforce
1 parent df032fc commit 48d23df

File tree

3 files changed

+69
-9
lines changed

3 files changed

+69
-9
lines changed

project/__main__.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from .handlers import bruteforce_handler, decrypt_handler, encrypt_handler, freq_analysis_handler
1+
from .handlers import bruteforce_handler, decrypt_handler, encrypt_handler, freq_analysis_handler, brute_freq_handler
2+
from colorama import Fore, Style
23
import argparse
34

45
parser = argparse.ArgumentParser(
@@ -26,10 +27,16 @@
2627
metavar='PLAIN', help='Cipher text to crack', type=str)
2728

2829
# -fr & --freq-analysis
29-
parser.add_argument('-fr', '--freq-analysis', nargs='+', metavar='CIPHER', help='Cipher text to crack by analysing', type=str)
30+
parser.add_argument('-fr', '--freq-analysis', nargs='+', metavar='CIPHER',
31+
help='Plain text to crack by analysing', type=str)
3032

3133
# -w & --wordlist
32-
parser.add_argument('-w', '--wordlist', nargs=1, metavar='WORDLIST', help='Path to the wordlist containing language words', type=str)
34+
parser.add_argument('-w', '--wordlist', nargs=1, metavar='WORDLIST',
35+
help='Path to the wordlist containing language words', type=str)
36+
37+
# -bfr & --brute-frequency
38+
parser.add_argument('-bfr', '--brute-frequency', nargs='+', metavar='CIPHER',
39+
help='Cipher to crack and analyse output for the text containing words in a wordlist')
3340

3441
args = parser.parse_args()
3542

@@ -39,6 +46,10 @@ def handle_args():
3946
# If key isn't in the args,
4047
if not args.key and (args.encrypt or args.decrypt):
4148
raise NameError("Key is not defined")
49+
# If brute frequency flag used,
50+
elif args.brute_frequency:
51+
brute_freq_handler(args)
52+
# If frequency flag used,
4253
elif args.freq_analysis:
4354
freq_analysis_handler(args)
4455
# If the bruteforce flag used
@@ -54,4 +65,4 @@ def handle_args():
5465
else:
5566
raise ValueError("No Arguments given")
5667
except Exception as e:
57-
print("Error:", e)
68+
print(f'{Fore.LIGHTRED_EX}Error: {e}{Style.RESET_ALL}')

project/crack.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,29 @@
11
from .crypt import ALPHEBET, decrypt
2+
from .utils import analyse_text
3+
from operator import itemgetter
4+
import re
5+
26

37
def bruteforce(text):
48
cracked = []
9+
# Iterate from 1 to length of the ALPHEBET
510
for i in range(1, len(ALPHEBET)):
611
cracked.append('Result with key ' + str(i) + ' ' + decrypt(text, i))
712
return cracked
13+
14+
15+
def brute_freq(text, wordlist):
16+
analysed = {}
17+
decrypted = []
18+
# Bruteforce and get all possibilities
19+
for i in range(len(ALPHEBET)):
20+
decrypted.append(decrypt(text, i))
21+
# Check whether the given words are present in the given wordlist or not
22+
for text in decrypted:
23+
text = re.sub(r'[^A-Za-z0-9 ]+', '', text)
24+
matches = analyse_text(text, wordlist)
25+
avg = float(matches) / len(text.split(' ')) * 100
26+
analysed[text] = avg
27+
# Sort the analysed texts by average
28+
analysed = dict(sorted(analysed.items(), key=itemgetter(1), reverse=True))
29+
return analysed

project/handlers.py

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from .crack import bruteforce
1+
from .crack import bruteforce, brute_freq
22
from .utils import write_file, analyse_text
33
from .crypt import encrypt, decrypt
4+
from colorama import Fore, Style
45
import re
56

67

@@ -66,12 +67,38 @@ def decrypt_handler(args):
6667

6768

6869
def freq_analysis_handler(args):
70+
# Check for missing arguments
71+
if not args.wordlist:
72+
raise ValueError("No Wordlist Found")
6973
text = ''
7074
a_value = ' '.join(args.freq_analysis)
75+
# Filter letters, numbers and spaces
7176
text = re.sub(r'[^A-Za-z0-9 ]+', '', a_value)
77+
# Analyse the frequency
7278
matches = analyse_text(text, ''.join(args.wordlist))
73-
l = len(text.split(' '))
7479
avg = float(matches) / len(text.split(' ')) * 100
75-
if avg > 80:
76-
print('True')
77-
print('False')
80+
if avg > 60:
81+
print(f'{Fore.GREEN}True with an average of {round(avg, 1)}%{Style.RESET_ALL}')
82+
return
83+
print(f'{Fore.YELLOW}False with an average of {round(avg, 1)}%{Style.RESET_ALL}')
84+
85+
86+
def brute_freq_handler(args):
87+
c_value = ' '.join(args.brute_frequency)
88+
# Get cipher text
89+
cipher = open(c_value, 'r').read() if args.sourceFile else c_value
90+
# Get analysed disctionary
91+
analyzed = brute_freq(cipher, ''.join(args.wordlist))
92+
# Write to the file,
93+
# If an output path specified
94+
if args.output:
95+
write_file(analyzed, args.output)
96+
else:
97+
found = False
98+
for i in analyzed:
99+
if analyzed[i] > 60:
100+
print(f'{Fore.GREEN}{round(analyzed[i], 1)}%{Style.RESET_ALL} : {i}')
101+
found = True
102+
if not found:
103+
print(
104+
f'{Fore.YELLOW}No Matching Sentences Found For The Given Wordlist{Style.RESET_ALL}')

0 commit comments

Comments
 (0)