Homework 05: hulk.py
This commit is contained in:
parent
25099bf998
commit
6d97679d1a
1 changed files with 69 additions and 22 deletions
87
homework05/hulk.py
Normal file → Executable file
87
homework05/hulk.py
Normal file → Executable file
|
|
@ -29,9 +29,9 @@ def sha1sum(s: str) -> str:
|
||||||
>>> sha1sum('a')
|
>>> sha1sum('a')
|
||||||
'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8'
|
'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8'
|
||||||
'''
|
'''
|
||||||
# TODO: Use the hashlib library to produce the SHA1 hex digest of the given
|
hashOfString = hashlib.sha1()
|
||||||
# string.
|
hashOfString.update(s.encode('utf-8'))
|
||||||
return ''
|
return hashOfString.hexdigest()
|
||||||
|
|
||||||
def permutations(length: int, alphabet: str=ALPHABET) -> Iterator[str]:
|
def permutations(length: int, alphabet: str=ALPHABET) -> Iterator[str]:
|
||||||
''' Recursively yield all permutations of alphabet up to given length.
|
''' Recursively yield all permutations of alphabet up to given length.
|
||||||
|
|
@ -42,9 +42,12 @@ def permutations(length: int, alphabet: str=ALPHABET) -> Iterator[str]:
|
||||||
ba
|
ba
|
||||||
bb
|
bb
|
||||||
'''
|
'''
|
||||||
# TODO: Use yield to create a generator function that recursively produces
|
if length == 0: # Base case
|
||||||
# all the permutations of the given alphabet up to the provided length.
|
yield ''
|
||||||
yield ''
|
else: # Recursive case
|
||||||
|
for prefix in alphabet:
|
||||||
|
for suffix in permutations(length - 1, alphabet):
|
||||||
|
yield prefix + suffix # this can be done in one line but I think this is more readble
|
||||||
|
|
||||||
def flatten(sequence: Iterable[Iterable[str]]) -> Iterator[str]:
|
def flatten(sequence: Iterable[Iterable[str]]) -> Iterator[str]:
|
||||||
''' Flatten sequence of iterables.
|
''' Flatten sequence of iterables.
|
||||||
|
|
@ -55,8 +58,10 @@ def flatten(sequence: Iterable[Iterable[str]]) -> Iterator[str]:
|
||||||
c
|
c
|
||||||
d
|
d
|
||||||
'''
|
'''
|
||||||
# TODO: Iterate through sequence and yield from each iterator in sequence.
|
for sub_iterable in sequence:
|
||||||
yield ''
|
yield from sub_iterable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def crack(hashes: set[str], length: int, alphabet: str=ALPHABET, prefix: str='') -> list[str]:
|
def crack(hashes: set[str], length: int, alphabet: str=ALPHABET, prefix: str='') -> list[str]:
|
||||||
''' Return all password permutations of specified length that are in hashes
|
''' Return all password permutations of specified length that are in hashes
|
||||||
|
|
@ -67,10 +72,14 @@ def crack(hashes: set[str], length: int, alphabet: str=ALPHABET, prefix: str='')
|
||||||
b
|
b
|
||||||
c
|
c
|
||||||
'''
|
'''
|
||||||
# TODO: Return list comprehension that iterates over a sequence of
|
matches = []
|
||||||
# candidate permutations and checks if the sha1sum of each candidate is in
|
for perm in permutations(length, alphabet):
|
||||||
# hashes.
|
candidate = prefix + perm
|
||||||
return []
|
if sha1sum(candidate) in hashes:
|
||||||
|
matches.append(candidate)
|
||||||
|
return matches
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def whack(arguments: tuple[set[str], int, str, str]) -> list[str]:
|
def whack(arguments: tuple[set[str], int, str, str]) -> list[str]:
|
||||||
''' Call the crack function with the specified list of arguments
|
''' Call the crack function with the specified list of arguments
|
||||||
|
|
@ -80,7 +89,8 @@ def whack(arguments: tuple[set[str], int, str, str]) -> list[str]:
|
||||||
b
|
b
|
||||||
c
|
c
|
||||||
'''
|
'''
|
||||||
return []
|
hashes, length, alphabet, prefix = arguments
|
||||||
|
return crack(hashes, length, alphabet, prefix)
|
||||||
|
|
||||||
def smash(hashes: set[str], length: int, alphabet: str=ALPHABET, prefix: str='', cores: int=1) -> Iterator[str]:
|
def smash(hashes: set[str], length: int, alphabet: str=ALPHABET, prefix: str='', cores: int=1) -> Iterator[str]:
|
||||||
''' Return all password permutations of specified length that are in hashes
|
''' Return all password permutations of specified length that are in hashes
|
||||||
|
|
@ -91,9 +101,15 @@ def smash(hashes: set[str], length: int, alphabet: str=ALPHABET, prefix: str='',
|
||||||
b
|
b
|
||||||
c
|
c
|
||||||
'''
|
'''
|
||||||
# TODO: Create generator expression with arguments to pass to whack and
|
arguments = ((hashes, length-1, alphabet, prefix + p) for p in alphabet)
|
||||||
# then use ProcessPoolExecutor to apply whack to all items in expression.
|
|
||||||
yield ''
|
# Use the ProcessPoolExecutor to make use of mutliple cores (specified by user)
|
||||||
|
with concurrent.futures.ProcessPoolExecutor(cores) as executor:
|
||||||
|
results = executor.map(whack, arguments)
|
||||||
|
|
||||||
|
return flatten(results) # return results after flattening them
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Main Execution
|
# Main Execution
|
||||||
|
|
||||||
|
|
@ -112,13 +128,44 @@ def main(arguments: list[str]=sys.argv[1:]) -> None:
|
||||||
length = 1
|
length = 1
|
||||||
prefix = ''
|
prefix = ''
|
||||||
|
|
||||||
# TODO: Parse command line arguments
|
# Parse command line arguments (I use the same while loop structure as searx.py)
|
||||||
|
i = 0
|
||||||
|
while i < len(arguments):
|
||||||
|
arg = arguments[i]
|
||||||
|
|
||||||
# TODO: Load hashes set
|
if arg == '-a':
|
||||||
|
alphabet = arguments[i+1]
|
||||||
|
i += 2
|
||||||
|
elif arg == '-c':
|
||||||
|
cores = int(arguments[i+1])
|
||||||
|
i += 2
|
||||||
|
elif arg == '-l':
|
||||||
|
length = int(arguments[i+1])
|
||||||
|
i += 2
|
||||||
|
elif arg == '-p':
|
||||||
|
prefix = arguments[i+1]
|
||||||
|
i += 2
|
||||||
|
elif arg == '-s':
|
||||||
|
hashes_path = arguments[i+1]
|
||||||
|
i += 2
|
||||||
|
elif arg == '-h':
|
||||||
|
usage(0)
|
||||||
|
else:
|
||||||
|
usage(1)
|
||||||
|
|
||||||
# TODO: Execute smash function
|
# Load hashes set
|
||||||
|
hashes = set()
|
||||||
|
with open(hashes_path) as hashfile:
|
||||||
|
for line in hashfile:
|
||||||
|
hashes.add(line.strip())
|
||||||
|
|
||||||
|
# Execute smash function and store results
|
||||||
|
results = smash(hashes, length, alphabet, prefix, cores)
|
||||||
|
|
||||||
|
# Print all found passwords
|
||||||
|
for password in results:
|
||||||
|
print(password)
|
||||||
|
|
||||||
# TODO: Print all found passwords
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue