-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
113 lines (88 loc) · 3.24 KB
/
main.py
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
112
113
import des
import time
import utils
import asyncio
import datetime
from functools import partial
from asyncio.events import AbstractEventLoop
from words_gen import generate_random_passwords
from concurrent.futures import ProcessPoolExecutor
def get_dates() -> list[str]:
date_range: list[str] = []
for year in range(1900, 2025):
for month in range(1, 13):
for day in range(1, 32):
date_range.append(f"{year:04d}{month:02d}{day:02d}")
return date_range
def get_chunks(n_threads: int, N: int) -> list[list[int, int]]:
chunk_size = N // n_threads
chunks = []
start_i = 0
for _ in range(n_threads):
end_i = start_i + chunk_size
if end_i > N:
end_i = N - 1
chunks.append(([start_i, end_i]))
start_i = end_i + 1
return chunks
def sequential_crack(passwords: list[str], dates: list[str]) -> None:
for password in passwords:
for date in dates:
encrypted = des.encrypt(date)
if encrypted == password:
print(f"Password found : {des.decrypt(utils.str_to_bin(encrypted))}")
break
def parallel(password: str, chunk: [[int, int]], dates: list[str]) -> None:
start_i, end_i = chunk[0], chunk[1]
for i in range(start_i, end_i):
encrypted = des.encrypt(dates[i])
if encrypted == password:
print(f"Password found: {des.decrypt(utils.str_to_bin(encrypted))}")
break
async def parallel_crack(passwords: list[str], dates: list[str], n_threads: int) -> None:
chunks = get_chunks(n_threads, len(dates))
with ProcessPoolExecutor() as process_pool:
for password in passwords:
loop: AbstractEventLoop = asyncio.get_event_loop()
calls: List[partial] = [
partial(parallel, password, chunk, dates)
for chunk in chunks
]
call_coros = []
for call in calls:
call_coros.append(loop.run_in_executor(process_pool, call))
await asyncio.gather(*call_coros)
async def main() -> None:
N_TESTS = 10
N_TO_CRACK = 5
start_date = datetime.date(1900, 1, 1)
end_date = datetime.date(2024, 12, 31)
dates = get_dates()
encrypted_passwords = []
for i in range(N_TESTS):
encrypted_passwords.append(generate_random_passwords(N_TO_CRACK, start_date, end_date))
times = []
speedups = []
start = time.time()
for i in range(N_TESTS):
sequential_crack(encrypted_passwords[i], dates)
end = time.time()
seqElapsed = (end - start) / N_TESTS * 1000
print(f'sequential time {seqElapsed} ms\n')
times.append(seqElapsed)
threads = [2, 4, 6, 8, 16, 32]
for n_thread in threads:
start = time.time()
for i in range(N_TESTS):
await parallel_crack(encrypted_passwords[i], dates, n_thread)
end = time.time()
parElapsed = (end - start) / N_TESTS * 1000
speedup = seqElapsed / parElapsed
print(f'{n_thread} threads time: {parElapsed} ms')
print(f'{n_thread} threads speed up: {speedup} ms')
times.append(parElapsed)
speedups.append(speedup)
print(times)
print(speedups)
if __name__ == '__main__':
asyncio.run(main())