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')
|
||||
'86f7e437faa5a7fce15d1ddcb9eaeaea377667b8'
|
||||
'''
|
||||
# TODO: Use the hashlib library to produce the SHA1 hex digest of the given
|
||||
# string.
|
||||
return ''
|
||||
hashOfString = hashlib.sha1()
|
||||
hashOfString.update(s.encode('utf-8'))
|
||||
return hashOfString.hexdigest()
|
||||
|
||||
def permutations(length: int, alphabet: str=ALPHABET) -> Iterator[str]:
|
||||
''' Recursively yield all permutations of alphabet up to given length.
|
||||
|
|
@ -42,9 +42,12 @@ def permutations(length: int, alphabet: str=ALPHABET) -> Iterator[str]:
|
|||
ba
|
||||
bb
|
||||
'''
|
||||
# TODO: Use yield to create a generator function that recursively produces
|
||||
# all the permutations of the given alphabet up to the provided length.
|
||||
yield ''
|
||||
if length == 0: # Base case
|
||||
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]:
|
||||
''' Flatten sequence of iterables.
|
||||
|
|
@ -55,8 +58,10 @@ def flatten(sequence: Iterable[Iterable[str]]) -> Iterator[str]:
|
|||
c
|
||||
d
|
||||
'''
|
||||
# TODO: Iterate through sequence and yield from each iterator in sequence.
|
||||
yield ''
|
||||
for sub_iterable in sequence:
|
||||
yield from sub_iterable
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
|
@ -67,10 +72,14 @@ def crack(hashes: set[str], length: int, alphabet: str=ALPHABET, prefix: str='')
|
|||
b
|
||||
c
|
||||
'''
|
||||
# TODO: Return list comprehension that iterates over a sequence of
|
||||
# candidate permutations and checks if the sha1sum of each candidate is in
|
||||
# hashes.
|
||||
return []
|
||||
matches = []
|
||||
for perm in permutations(length, alphabet):
|
||||
candidate = prefix + perm
|
||||
if sha1sum(candidate) in hashes:
|
||||
matches.append(candidate)
|
||||
return matches
|
||||
|
||||
|
||||
|
||||
def whack(arguments: tuple[set[str], int, str, str]) -> list[str]:
|
||||
''' 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
|
||||
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]:
|
||||
''' 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
|
||||
c
|
||||
'''
|
||||
# TODO: Create generator expression with arguments to pass to whack and
|
||||
# then use ProcessPoolExecutor to apply whack to all items in expression.
|
||||
yield ''
|
||||
arguments = ((hashes, length-1, alphabet, prefix + p) for p in alphabet)
|
||||
|
||||
# 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
|
||||
|
||||
|
|
@ -112,13 +128,44 @@ def main(arguments: list[str]=sys.argv[1:]) -> None:
|
|||
length = 1
|
||||
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__':
|
||||
main()
|
||||
|
|
|
|||
Loading…
Reference in a new issue