As part of our final project we had 4 different options, 3 involving code, so here is my implementation.
Overview: As part of this project, you will write a program that will measure password security by employing a variation of the dictionary attack. Given a file of a limited amount of words(100~200, no more than 500), allow the end user to pick up to any three words(due to limited computing power) from the word list to concatenate together in any order and form a random password. Write a program to crack that random password, and count how many attempts were made or/and how much time was consumed using a dictionary attack. Compare the efficiency of different hash algorithms. Plot a graph to visualize the difference.
the
of
to
and
a
in
is
it
you
that
he
was
for
on
are
with
as
I
his
they
be
at
one
have
this
from
or
had
by
not
word
but
what
some
the
of
to
and
a
in
is
it
you
that
he
was
for
on
are
with
as
I
his
they
be
at
one
have
this
from
or
had
by
not
word
but
what
some
we
can
out
other
were
all
there
when
up
use
your
how
said
an
each
she
which
do
their
time
if
will
way
about
many
then
them
write
would
like
so
these
her
long
make
thing
see
him
two
has
look
more
day
could
go
come
did
number
sound
no
most
people
my
over
know
water
than
call
first
who
may
down
side
been
now
find
any
new
work
part
take
get
place
made
live
where
after
back
little
only
round
man
year
came
show
every
good
me
give
our
under
name
very
through
just
form
sentence
great
think
say
help
low
line
differ
turn
cause
much
mean
before
move
right
boy
old
too
same
tell
does
set
three
want
air
well
also
play
small
end
put
home
read
hand
port
large
spell
add
even
land
here
must
big
high
such
follow
act
why
ask
men
change
went
light
kind
off
need
house
picture
try
us
again
animal
point
mother
world
near
build
self
earth
father
head
stand
own
page
should
country
found
answer
school
grow
study
still
learn
plant
cover
food
sun
four
between
state
keep
eye
never
last
let
thought
city
tree
cross
farm
hard
start
might
story
saw
far
sea
draw
left
late
run
don't
while
press
close
night
real
life
few
north
open
seem
together
next
white
children
begin
got
walk
example
ease
paper
group
always
music
those
both
mark
often
letter
until
mile
river
car
feet
care
second
book
carry
took
science
eat
room
friend
began
idea
fish
mountain
stop
once
base
hear
horse
cut
sure
watch
color
face
wood
main
enough
plain
girl
usual
young
ready
above
ever
red
list
though
feel
talk
bird
soon
body
dog
family
direct
pose
leave
song
measure
door
product
black
short
numeral
class
wind
question
happen
complete
ship
area
half
rock
order
fire
south
problem
piece
told
knew
pass
since
top
whole
king
space
heard
best
hour
better
true
during
hundred
five
remember
step
early
hold
west
ground
interest
reach
fast
verb
sing
listen
six
table
travel
less
morning
ten
simple
several
vowel
toward
war
lay
against
pattern
slow
center
love
person
money
serve
appear
road
map
rain
rule
govern
pull
cold
notice
voice
unit
power
town
fine
certain
fly
fall
lead
cry
dark
machine
note
wait
plan
figure
star
box
noun
field
rest
correct
able
pound
done
beauty
drive
stood
contain
front
teach
week
final
gave
green
oh
quick
develop
ocean
warm
free
minute
strong
special
mind
behind
clear
tail
produce
fact
street
inch
multiply
nothing
course
stay
wheel
full
force
blue
object
decide
surface
deep
moon
island
foot
system
busy
test
record
boat
common
gold
possible
plane
stead
dry
wonder
laugh
thousand
ago
ran
check
game
shape
equate
hot
miss
brought
heat
snow
tire
bring
yes
distant
fill
east
paint
language
among
the
of
to
and
a
in
is
it
you
that
he
was
for
on
are
with
as
I
his
they
be
at
one
have
this
from
or
had
by
not
word
but
what
some
we
can
out
other
were
all
there
when
up
use
your
how
said
an
each
she
which
do
their
time
if
will
way
about
many
then
them
write
would
like
so
these
her
long
make
thing
see
him
two
has
look
more
day
could
go
come
did
number
sound
no
most
people
my
over
know
water
than
call
first
who
may
down
side
been
now
find
any
new
work
part
take
get
place
made
live
where
after
back
little
only
round
man
year
came
show
every
good
me
give
our
under
name
very
through
just
form
sentence
great
think
say
help
low
line
differ
turn
cause
much
mean
before
move
right
boy
old
too
same
tell
does
set
three
want
air
well
also
play
small
end
put
home
read
hand
port
large
spell
add
even
land
here
must
big
high
such
follow
act
why
ask
men
change
went
light
kind
off
need
house
picture
try
us
again
animal
point
mother
world
near
build
self
earth
father
head
stand
own
page
should
country
found
answer
school
grow
study
still
learn
plant
cover
food
sun
four
between
state
keep
eye
never
last
let
thought
city
tree
cross
farm
hard
start
might
story
saw
far
sea
draw
left
late
run
don't
while
press
close
night
real
life
few
north
open
seem
together
next
white
children
begin
got
walk
example
ease
paper
group
always
music
those
both
mark
often
letter
until
mile
river
car
feet
care
second
book
carry
took
science
eat
room
friend
began
idea
fish
mountain
stop
once
base
hear
horse
cut
sure
watch
color
face
wood
main
enough
plain
girl
usual
young
ready
above
ever
red
list
though
feel
talk
bird
soon
body
dog
family
direct
pose
leave
song
measure
door
product
black
short
numeral
class
wind
question
happen
complete
ship
area
half
rock
order
fire
south
problem
piece
told
knew
pass
since
top
whole
king
space
heard
best
hour
better
true
during
hundred
five
remember
step
early
hold
west
ground
interest
reach
fast
verb
sing
listen
six
table
travel
less
morning
ten
simple
several
vowel
toward
war
lay
against
pattern
slow
center
love
person
money
serve
appear
road
map
rain
rule
govern
pull
cold
notice
voice
unit
power
town
fine
certain
fly
fall
lead
cry
dark
machine
note
wait
plan
figure
star
box
noun
field
rest
correct
able
pound
done
beauty
drive
stood
contain
front
teach
week
final
gave
green
oh
quick
develop
ocean
warm
free
minute
strong
special
mind
behind
clear
tail
produce
fact
street
inch
multiply
nothing
course
stay
wheel
full
force
blue
object
decide
surface
deep
moon
island
foot
system
busy
test
record
boat
common
gold
possible
plane
stead
dry
wonder
laugh
thousand
ago
ran
check
game
shape
equate
hot
miss
brought
heat
snow
tire
bring
yes
distant
fill
east
paint
language
among
grand
ball
yet
wave
drop
heart
am
present
heavy
dance
engine
position
arm
wide
sail
material
size
vary
settle
speak
weight
general
ice
matter
circle
pair
include
divide
syllable
felt
perhaps
pick
sudden
count
square
reason
length
represent
art
subject
region
energy
hunt
probable
bed
brother
egg
ride
cell
believe
fraction
forest
sit
race
window
store
summer
train
sleep
prove
lone
leg
exercise
wall
catch
mount
wish
sky
board
joy
winter
sat
written
wild
instrument
kept
glass
grass
cow
job
edge
sign
visit
past
soft
fun
bright
gas
weather
month
million
bear
finish
happy
hope
flower
clothe
strange
gone
jump
baby
eight
village
meet
root
buy
raise
solve
metal
whether
push
seven
paragraph
third
shall
held
hair
describe
cook
floor
either
result
burn
hill
safe
cat
century
consider
type
law
bit
coast
copy
phrase
silent
tall
sand
soil
roll
temperature
finger
industry
value
fight
lie
beat
excite
natural
view
sense
ear
else
quite
broke
case
middle
kill
son
lake
moment
scale
loud
spring
observe
child
straight
consonant
nation
dictionary
milk
speed
method
organ
pay
age
section
dress
cloud
surprise
quiet
stone
tiny
climb
cool
design
poor
lot
experiment
bottom
key
iron
single
stick
flat
twenty
skin
smile
crease
hole
trade
melody
trip
office
receive
row
mouth
exact
symbol
die
least
trouble
shout
except
wrote
seed
tone
join
suggest
clean
break
lady
yard
rise
bad
blow
oil
blood
touch
grew
cent
mix
team
wire
cost
lost
brown
wear
garden
equal
sent
choose
fell
fit
flow
fair
bank
collect
save
control
decimal
gentle
woman
captain
practice
separate
difficult
doctor
please
protect
noon
whose
locate
ring
character
insect
caught
period
indicate
radio
spoke
atom
human
history
effect
electric
expect
crop
modern
element
hit
student
corner
party
supply
bone
rail
imagine
provide
agree
thus
capital
won't
chair
danger
fruit
rich
thick
soldier
process
operate
guess
necessary
sharp
wing
create
neighbor
wash
bat
rather
crowd
corn
compare
poem
string
bell
depend
meat
rub
tube
famous
dollar
stream
fear
sight
thin
triangle
planet
hurry
chief
colony
clock
mine
tie
enter
major
fresh
search
send
yellow
gun
allow
dead
spot
desert
suit
current
lift
rose
continue
block
chart
hat
sell
success
company
subtract
event
particular
deal
swim
term
opposite
wife
shoe
shoulder
spread
arrange
camp
invent
cotton
born
determine
quart
nine
truck
noise
level
chance
gather
shop
stretch
throw
shine
property
column
molecule
select
wrong
gray
repeat
require
broad
prepare
salt
nose
plural
anger
claim
continent
oxygen
sugar
death
pretty
skill
women
season
solution
magnet
silver
thank
branch
match
suffix
especially
fig
afraid
huge
sister
steel
discuss
forward
similar
guide
experience
score
apple
bought
led
pitch
coat
mass
card
band
rope
slip
win
dream
evening
condition
feed
tool
total
basic
smell
valley
nor
double
seat
arrive
master
track
parent
shore
division
sheet
substance
favor
connect
post
spend
chord
fat
glad
original
share
station
dad
bread
charge
proper
bar
offer
segment
slave
duck
instant
market
degree
populate
chick
dear
enemy
reply
drink
occur
support
speech
nature
range
steam
motion
path
liquid
log
meant
quotient
teeth
shell
neck
The main method is the thing that will actually call the different Hash Test functions as well as get user input and latter on make the graphs. The main function is largely the same across all functions except for the call to the function replacing the HashFunction that is currently in the code.
import itertools
import hashlib
import multiprocessing.shared_memory
import matplotlib as plt
import time
import multiprocessingÂ
import threading
import functoolsÂ
import cProfile
import math
import ctypes
#Converges the geometric series for when starting at 1
def geometricSeries(a: int, r: int, n: int):
    return a * r * ((r ** n - 1) // (r - 1))Â
if __name__ == "__main__":
    wordLimit = 3
    dictonaryName = "MediumDictionary.txt"
    hashAlgorithms = ['sha256', 'sha512']
    f = open(dictonaryName, "r")
    words = f.read().splitlines()
    f.close()
    maxCount = geometricSeries(1,len(words),wordLimit)
    print(f"Longest Password is {words[-1] * wordLimit} and will take around {maxCount} iterations and around {maxCount * 6e-7} seconds")
    password = input("Enter Password: ")
    while password != "q":
        for h in hashAlgorithms:
            hash = hashlib.new(h)
            hash.update(password.encode()) #Hashes the password
            print(f"{h.capitalize()} Hash: {hash.hexdigest()}") #Prints nice Hex
            breakCount, breakTime, value = HashFunction(wordLimit, words, hash.digest(), h)
            cProfile.run('HashFunction(wordLimit, words, hash.digest(), h)')
            print(breakCount, breakTime, value)
        password = input("Enter Password: ")
    print("Done")Â
The first approach was of course to do a simple for loop which ended up taking around ~3 minutes to do the hardest password in the 500 word dictionary of amongamongamong. In the profiler we see that it takes this long due solely to having lots of iterations with a total of 125,250,500 iterations of the loop.
def hashAttack(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    count = 0
    for i in range(1, wordLimit + 1):
        perms = itertools.product(words, repeat=i)
        for p in perms:
            test = "".join([s for s in p]).encode()
            hash = hashlib.new(algorithm)
            hash.update(test)
            count += 1
            if (hash.digest() == password):
                return count, (time.time_ns() - start) / 1e9, test
    return None, NoneÂ
Longest Password is amongamongamong and will take around 125250500 iterations and around 75.1503 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
         876753507 function calls in 363.562 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
        1  0.000  0.000 363.562 363.562 <string>:1(<module>)
        1 177.490 177.490 363.562 363.562 DicAttack.py:17(hashAttack)
125250500 Â 22.976Â Â 0.000 Â 22.976Â Â 0.000 DicAttack.py:23(<listcomp>)
125250500 Â 35.692Â Â 0.000 Â 74.187Â Â 0.000 hashlib.py:152(__hash_new)
125250500 Â 38.495Â Â 0.000 Â 38.495Â Â 0.000 {built-in method _hashlib.new}
        1  0.000  0.000 363.562 363.562 {built-in method builtins.exec}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
125250501 Â 48.585Â Â 0.000 Â 48.585Â Â 0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
125250500 Â 12.388Â Â 0.000 Â 12.388Â Â 0.000 {method 'encode' of 'str' objects}
125250500 Â 15.395Â Â 0.000 Â 15.395Â Â 0.000 {method 'join' of 'str' objects}
125250500 Â 12.541Â Â 0.000 Â 12.541Â Â 0.000 {method 'update' of '_hashlib.HASH' objects}
125250500 168.0729339 b'amongamongamong'
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
         876753507 function calls in 385.726 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
        1  0.000  0.000 385.726 385.726 <string>:1(<module>)
        1 177.534 177.534 385.726 385.726 DicAttack.py:17(hashAttack)
125250500 Â 20.505Â Â 0.000 Â 20.505Â Â 0.000 DicAttack.py:23(<listcomp>)
125250500 Â 35.177Â Â 0.000 Â 73.378Â Â 0.000 hashlib.py:152(__hash_new)
125250500 Â 38.201Â Â 0.000 Â 38.201Â Â 0.000 {built-in method _hashlib.new}
        1  0.000  0.000 385.726 385.726 {built-in method builtins.exec}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
125250501 Â 73.758Â Â 0.000 Â 73.758Â Â 0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
125250500 Â 12.188Â Â 0.000 Â 12.188Â Â 0.000 {method 'encode' of 'str' objects}
125250500 Â 15.634Â Â 0.000 Â 15.634Â Â 0.000 {method 'join' of 'str' objects}
125250500 Â 12.729Â Â 0.000 Â 12.729Â Â 0.000 {method 'update' of '_hashlib.HASH' objects}
125250500 189.4634892 b'amongamongamong'
Enter Password: q
Done
Since the for loop took so long due to the number of iterations then the easiest way to fix that is to parallelize it leading to using a multiprocessor pool. This approach took around ~75 seconds to do the hardest password in the 500 word dictionary of amongamongamong. In the profiler we see that the bottle neck is using locks, which I suspect is due to the multiprocessor since my code doesn't use locks. However there is a even bigger issue which is no early termination meaning it will test every possible permutation instead of only testing a few.
def run(password, algorithm, p):
    test = "".join([s for s in p]).encode()
    hash = hashlib.new(algorithm)
    hash.update(test)
    if (hash.digest() == password):
        return True
    return None
def multiHashAttack(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    count = 1
    func = functools.partial(run, password, algorithm)
    pool = multiprocessing.Pool()
    for i in range(1, wordLimit + 1):
        perms = itertools.product(words, repeat=i)
        values = pool.map(func, perms)
        try:
            count += values.index(True)
            pool.close()
            pool.join()
            return count, (time.time_ns() - start) / 1e9, None
        except:
            count += len(values)
    pool.close()
    pool.join()
    return None, NoneÂ
Longest Password is amongamongamong and will take around 125250500 iterations and around 75.1503 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
         4628 function calls in 87.265 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
       55  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        3  0.000  0.000  0.000  0.000 <frozen ntpath>:107(join)
        6  0.000  0.000  0.000  0.000 <frozen ntpath>:154(splitdrive)
       16  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       16  0.000  0.000  0.000  0.000 <frozen ntpath>:87(isabs)
        1  0.159  0.159  87.265  87.265 <string>:1(<module>)
        1  0.002  0.002  87.104  87.104 DicAttack.py:39(multiHashAttack)
       19  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       19  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        6  0.000  0.000  0.000  0.000 connection.py:118(__init__)
        6  0.000  0.000  0.000  0.000 connection.py:131(__del__)
       68  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
        4  0.000  0.000  0.000  0.000 connection.py:143(_check_writable)
      128  0.000  0.000  0.000  0.000 connection.py:159(readable)
      128  0.000  0.000  0.000  0.000 connection.py:164(writable)
       64  0.000  0.000  0.000  0.000 connection.py:169(fileno)
        4  0.000  0.000  0.000  0.000 connection.py:182(send_bytes)
        6  0.000  0.000  0.000  0.000 connection.py:277(_close)
        4  0.000  0.000  0.000  0.000 connection.py:284(_send_bytes)
        3  0.000  0.000  0.002  0.001 connection.py:552(Pipe)
        3  0.001  0.000  0.002  0.001 connection.py:70(arbitrary_address)
       64  0.000  0.000  0.001  0.000 connection.py:973(reduce_pipe_connection)
        3  0.000  0.000  0.003  0.001 context.py:110(SimpleQueue)
        1  0.000  0.000  0.097  0.097 context.py:115(Pool)
        6  0.000  0.000  0.000  0.000 context.py:187(get_context)
        3  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
        1  0.000  0.000  0.000  0.000 context.py:237(get_context)
       16  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       16  0.000  0.000  0.087  0.005 context.py:333(_Popen)
      160  0.000  0.000  0.000  0.000 context.py:365(get_spawning_popen)
       32  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
       64  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 pool.py:157(__init__)
       16  0.000  0.000  0.001  0.000 pool.py:179(Process)
        1  0.000  0.000  0.097  0.097 pool.py:183(__init__)
        1  0.000  0.000  0.000  0.000 pool.py:266(__del__)
        1  0.000  0.000  0.000  0.000 pool.py:279(_get_sentinels)
        1  0.000  0.000  0.089  0.089 pool.py:305(_repopulate_pool)
        1  0.000  0.000  0.089  0.089 pool.py:314(_repopulate_pool_static)
        1  0.000  0.000  0.003  0.003 pool.py:345(_setup_queues)
        3  0.000  0.000  0.000  0.000 pool.py:351(_check_running)
        3  0.000  0.000  85.196  28.399 pool.py:362(map)
        3  7.982  2.661  8.133  2.711 pool.py:471(_map_async)
        1  0.000  0.000  0.000  0.000 pool.py:647(close)
        1  0.000  0.000  0.336  0.336 pool.py:659(join)
        1  0.000  0.000  0.000  0.000 pool.py:671(_help_stuff_finish)
        1  0.000  0.000  0.000  0.000 pool.py:680(_terminate_pool)
        3  0.000  0.000  0.000  0.000 pool.py:747(__init__)
        3  0.000  0.000  0.000  0.000 pool.py:756(ready)
        3  0.000  0.000  77.063  25.688 pool.py:764(wait)
        3  0.000  0.000  77.063  25.688 pool.py:767(get)
        3  0.151  0.050  0.151  0.050 pool.py:796(__init__)
      168  0.000  0.000  0.335  0.002 popen_spawn_win32.py:103(wait)
      152  0.000  0.000  0.001  0.000 popen_spawn_win32.py:121(poll)
       16  0.000  0.000  0.001  0.000 popen_spawn_win32.py:29(_close_handles)
       16  0.001  0.000  0.087  0.005 popen_spawn_win32.py:45(__init__)
       80  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
       32  0.000  0.000  0.000  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       16  0.000  0.000  0.088  0.006 process.py:110(start)
       16  0.000  0.000  0.335  0.021 process.py:142(join)
       16  0.000  0.000  0.000  0.000 process.py:153(is_alive)
       32  0.000  0.000  0.000  0.000 process.py:189(name)
       16  0.000  0.000  0.000  0.000 process.py:193(name)
       16  0.000  0.000  0.000  0.000 process.py:205(daemon)
       16  0.000  0.000  0.000  0.000 process.py:213(authkey)
       16  0.000  0.000  0.000  0.000 process.py:224(exitcode)
       32  0.000  0.000  0.001  0.000 process.py:350(__reduce__)
       35  0.000  0.000  0.000  0.000 process.py:37(current_process)
       16  0.000  0.000  0.001  0.000 process.py:61(_cleanup)
       16  0.000  0.000  0.001  0.000 process.py:80(__init__)
       32  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
       64  0.000  0.000  0.000  0.000 process.py:99(_check_closed)
        3  0.000  0.000  0.003  0.001 queues.py:339(__init__)
       32  0.000  0.000  0.000  0.000 queues.py:355(__getstate__)
        4  0.000  0.000  0.000  0.000 queues.py:369(put)
        6  0.000  0.000  0.000  0.000 random.py:480(choices)
        6  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
       64  0.000  0.000  0.001  0.000 reduction.py:106(__init__)
       36  0.000  0.000  0.001  0.000 reduction.py:38(__init__)
        4  0.000  0.000  0.000  0.000 reduction.py:48(dumps)
       32  0.000  0.000  0.005  0.000 reduction.py:58(dump)
       32  0.000  0.000  0.000  0.000 reduction.py:71(duplicate)
       16  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       16  0.001  0.000  0.001  0.000 spawn.py:160(get_preparation_data)
       32  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       16  0.000  0.000  0.001  0.000 spawn.py:83(get_command_line)
       48  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       16  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       16  0.000  0.000  0.000  0.000 subprocess.py:300(_args_from_interpreter_flags)
       32  0.000  0.000  0.000  0.000 synchronize.py:100(__getstate__)
        3  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        3  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        3  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        3  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        6  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        6  0.000  0.000  0.001  0.000 tempfile.py:154(__next__)
        3  0.000  0.000  0.000  0.000 tempfile.py:230(_get_candidate_names)
        3  0.000  0.000  0.001  0.000 tempfile.py:401(mktemp)
        3  0.000  0.000  0.000  0.000 tempfile.py:77(_exists)
        3  0.000  0.000  0.000  0.000 threading.py:1051(_stop)
        6  0.000  0.000  0.001  0.000 threading.py:1087(join)
        6  0.000  0.000  0.001  0.000 threading.py:1125(_wait_for_tstate_lock)
        2  0.000  0.000  0.000  0.000 threading.py:1192(is_alive)
        6  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        3  0.000  0.000  0.000  0.000 threading.py:1221(daemon)
        3  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
       12  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        6  0.000  0.000  0.000  0.000 threading.py:243(__init__)
        6  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
        6  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
        6  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
        6  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
        6  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
        6  0.000  0.000  77.067  12.844 threading.py:295(wait)
        6  0.000  0.000  0.000  0.000 threading.py:562(__init__)
       15  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        6  0.000  0.000  77.067  12.844 threading.py:611(wait)
        3  0.000  0.000  0.000  0.000 threading.py:811(_newname)
        3  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        3  0.000  0.000  0.004  0.001 threading.py:945(start)
       17  0.000  0.000  0.000  0.000 util.py:189(__init__)
       17  0.000  0.000  0.001  0.000 util.py:208(__call__)
       17  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
       29  0.000  0.000  0.000  0.000 util.py:48(debug)
       12  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
       12  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        3  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
      118  0.001  0.000  0.001  0.000 {built-in method _winapi.CloseHandle}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.ConnectNamedPipe}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFile}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateNamedPipe}
       16  0.000  0.000  0.000  0.000 {built-in method _winapi.CreatePipe}
       16  0.078  0.005  0.078  0.005 {built-in method _winapi.CreateProcess}
       96  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
       96  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       16  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
       64  0.000  0.000  0.000  0.000 {built-in method _winapi.OpenProcess}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.SetNamedPipeHandleState}
      136  0.335  0.002  0.335  0.002 {built-in method _winapi.WaitForSingleObject}
        4  0.000  0.000  0.000  0.000 {built-in method _winapi.WriteFile}
        3  0.000  0.000  0.000  0.000 {built-in method builtins.divmod}
        1  0.001  0.001  87.265  87.265 {built-in method builtins.exec}
      342  0.000  0.000  0.000  0.000 {built-in method builtins.getattr}
        5  0.000  0.000  0.000  0.000 {built-in method builtins.hasattr}
       55  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
       33  0.000  0.000  0.000  0.000 {built-in method builtins.len}
      120  0.000  0.000  0.000  0.000 {built-in method builtins.max}
       45  0.000  0.000  0.001  0.000 {built-in method builtins.next}
       16  0.000  0.000  0.000  0.000 {built-in method io.open}
       48  0.000  0.000  0.000  0.000 {built-in method math.floor}
       16  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       16  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        1  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       41  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       16  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
      187  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        3  0.000  0.000  0.000  0.000 {built-in method nt.lstat}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
        7  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
        6  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
       16  0.000  0.000  0.000  0.000 {method '__exit__' of '_io._IOBase' objects}
        3  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
        6  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
       27  77.067  2.854  77.067  2.854 {method 'acquire' of '_thread.lock' objects}
       35  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
        6  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
       16  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
       52  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       16  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
       51  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       36  0.002  0.000  0.004  0.000 {method 'dump' of '_pickle.Pickler' objects}
        6  0.000  0.000  0.000  0.000 {method 'find' of 'str' objects}
       16  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
        4  0.000  0.000  0.000  0.000 {method 'getbuffer' of '_io.BytesIO' objects}
       19  1.472  0.077  1.472  0.077 {method 'index' of 'list' objects}
       32  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
       54  0.000  0.000  0.000  0.000 {method 'join' of 'str' objects}
        3  0.000  0.000  0.000  0.000 {method 'locked' of '_thread.lock' objects}
        3  0.000  0.000  0.000  0.000 {method 'put' of '_queue.SimpleQueue' objects}
       48  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
        9  0.000  0.000  0.000  0.000 {method 'release' of '_thread.lock' objects}
       35  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
       55  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
       32  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
       52  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
        3  0.000  0.000  0.000  0.000 {method 'upper' of 'str' objects}
125250500 72.8165352 None
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
         4628 function calls in 82.392 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
       55  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        3  0.000  0.000  0.000  0.000 <frozen ntpath>:107(join)
        6  0.000  0.000  0.000  0.000 <frozen ntpath>:154(splitdrive)
       16  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       16  0.000  0.000  0.000  0.000 <frozen ntpath>:87(isabs)
        1  0.146  0.146  82.392  82.392 <string>:1(<module>)
        1  0.001  0.001  82.245  82.245 DicAttack.py:39(multiHashAttack)
       19  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       19  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        6  0.000  0.000  0.000  0.000 connection.py:118(__init__)
        6  0.000  0.000  0.000  0.000 connection.py:131(__del__)
       68  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
        4  0.000  0.000  0.000  0.000 connection.py:143(_check_writable)
      128  0.000  0.000  0.000  0.000 connection.py:159(readable)
      128  0.000  0.000  0.000  0.000 connection.py:164(writable)
       64  0.000  0.000  0.000  0.000 connection.py:169(fileno)
        4  0.000  0.000  0.000  0.000 connection.py:182(send_bytes)
        6  0.000  0.000  0.000  0.000 connection.py:277(_close)
        4  0.000  0.000  0.000  0.000 connection.py:284(_send_bytes)
        3  0.000  0.000  0.001  0.000 connection.py:552(Pipe)
        3  0.000  0.000  0.000  0.000 connection.py:70(arbitrary_address)
       64  0.000  0.000  0.001  0.000 connection.py:973(reduce_pipe_connection)
        3  0.000  0.000  0.001  0.000 context.py:110(SimpleQueue)
        1  0.000  0.000  0.083  0.083 context.py:115(Pool)
        6  0.000  0.000  0.000  0.000 context.py:187(get_context)
        3  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
        1  0.000  0.000  0.000  0.000 context.py:237(get_context)
       16  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       16  0.000  0.000  0.077  0.005 context.py:333(_Popen)
      160  0.000  0.000  0.000  0.000 context.py:365(get_spawning_popen)
       32  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
       64  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 pool.py:157(__init__)
       16  0.000  0.000  0.001  0.000 pool.py:179(Process)
        1  0.000  0.000  0.082  0.082 pool.py:183(__init__)
        1  0.000  0.000  0.000  0.000 pool.py:266(__del__)
        1  0.000  0.000  0.000  0.000 pool.py:279(_get_sentinels)
        1  0.000  0.000  0.079  0.079 pool.py:305(_repopulate_pool)
        1  0.000  0.000  0.079  0.079 pool.py:314(_repopulate_pool_static)
        1  0.000  0.000  0.001  0.001 pool.py:345(_setup_queues)
        3  0.000  0.000  0.000  0.000 pool.py:351(_check_running)
        3  0.000  0.000  80.362  26.787 pool.py:362(map)
        3  8.624  2.875  8.758  2.919 pool.py:471(_map_async)
        1  0.000  0.000  0.000  0.000 pool.py:647(close)
        1  0.000  0.000  0.277  0.277 pool.py:659(join)
        1  0.000  0.000  0.000  0.000 pool.py:671(_help_stuff_finish)
        1  0.000  0.000  0.000  0.000 pool.py:680(_terminate_pool)
        3  0.000  0.000  0.000  0.000 pool.py:747(__init__)
        3  0.000  0.000  0.000  0.000 pool.py:756(ready)
        3  0.000  0.000  71.604  23.868 pool.py:764(wait)
        3  0.000  0.000  71.604  23.868 pool.py:767(get)
        3  0.134  0.045  0.134  0.045 pool.py:796(__init__)
      168  0.000  0.000  0.276  0.002 popen_spawn_win32.py:103(wait)
      152  0.000  0.000  0.000  0.000 popen_spawn_win32.py:121(poll)
       16  0.000  0.000  0.001  0.000 popen_spawn_win32.py:29(_close_handles)
       16  0.001  0.000  0.077  0.005 popen_spawn_win32.py:45(__init__)
       80  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
       32  0.000  0.000  0.000  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       16  0.000  0.000  0.078  0.005 process.py:110(start)
       16  0.000  0.000  0.276  0.017 process.py:142(join)
       16  0.000  0.000  0.000  0.000 process.py:153(is_alive)
       32  0.000  0.000  0.000  0.000 process.py:189(name)
       16  0.000  0.000  0.000  0.000 process.py:193(name)
       16  0.000  0.000  0.000  0.000 process.py:205(daemon)
       16  0.000  0.000  0.000  0.000 process.py:213(authkey)
       16  0.000  0.000  0.000  0.000 process.py:224(exitcode)
       32  0.000  0.000  0.000  0.000 process.py:350(__reduce__)
       35  0.000  0.000  0.000  0.000 process.py:37(current_process)
       16  0.000  0.000  0.001  0.000 process.py:61(_cleanup)
       16  0.000  0.000  0.001  0.000 process.py:80(__init__)
       32  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
       64  0.000  0.000  0.000  0.000 process.py:99(_check_closed)
        3  0.000  0.000  0.001  0.000 queues.py:339(__init__)
       32  0.000  0.000  0.000  0.000 queues.py:355(__getstate__)
        4  0.000  0.000  0.001  0.000 queues.py:369(put)
        6  0.000  0.000  0.000  0.000 random.py:480(choices)
        6  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
       64  0.000  0.000  0.001  0.000 reduction.py:106(__init__)
       36  0.000  0.000  0.001  0.000 reduction.py:38(__init__)
        4  0.000  0.000  0.000  0.000 reduction.py:48(dumps)
       32  0.001  0.000  0.005  0.000 reduction.py:58(dump)
       32  0.000  0.000  0.000  0.000 reduction.py:71(duplicate)
       16  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       16  0.000  0.000  0.001  0.000 spawn.py:160(get_preparation_data)
       32  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       16  0.000  0.000  0.001  0.000 spawn.py:83(get_command_line)
       48  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       16  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       16  0.000  0.000  0.000  0.000 subprocess.py:300(_args_from_interpreter_flags)
       32  0.000  0.000  0.000  0.000 synchronize.py:100(__getstate__)
        3  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        3  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        3  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        3  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        6  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        6  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        3  0.000  0.000  0.000  0.000 tempfile.py:230(_get_candidate_names)
        3  0.000  0.000  0.000  0.000 tempfile.py:401(mktemp)
        3  0.000  0.000  0.000  0.000 tempfile.py:77(_exists)
        3  0.000  0.000  0.000  0.000 threading.py:1051(_stop)
        6  0.000  0.000  0.001  0.000 threading.py:1087(join)
        6  0.000  0.000  0.001  0.000 threading.py:1125(_wait_for_tstate_lock)
        2  0.000  0.000  0.000  0.000 threading.py:1192(is_alive)
        6  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        3  0.000  0.000  0.000  0.000 threading.py:1221(daemon)
        3  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
       12  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        6  0.000  0.000  0.000  0.000 threading.py:243(__init__)
        6  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
        6  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
        6  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
        6  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
        6  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
        6  0.000  0.000  71.606  11.934 threading.py:295(wait)
        6  0.000  0.000  0.000  0.000 threading.py:562(__init__)
       15  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        6  0.000  0.000  71.607  11.934 threading.py:611(wait)
        3  0.000  0.000  0.000  0.000 threading.py:811(_newname)
        3  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        3  0.000  0.000  0.003  0.001 threading.py:945(start)
       17  0.000  0.000  0.000  0.000 util.py:189(__init__)
       17  0.000  0.000  0.001  0.000 util.py:208(__call__)
       17  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
       29  0.000  0.000  0.000  0.000 util.py:48(debug)
       12  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
       12  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        3  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
      118  0.001  0.000  0.001  0.000 {built-in method _winapi.CloseHandle}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.ConnectNamedPipe}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFile}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateNamedPipe}
       16  0.000  0.000  0.000  0.000 {built-in method _winapi.CreatePipe}
       16  0.068  0.004  0.068  0.004 {built-in method _winapi.CreateProcess}
       96  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
       96  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       16  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
       64  0.000  0.000  0.000  0.000 {built-in method _winapi.OpenProcess}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.SetNamedPipeHandleState}
      136  0.276  0.002  0.276  0.002 {built-in method _winapi.WaitForSingleObject}
        4  0.000  0.000  0.000  0.000 {built-in method _winapi.WriteFile}
        3  0.000  0.000  0.000  0.000 {built-in method builtins.divmod}
        1  0.000  0.000  82.392  82.392 {built-in method builtins.exec}
      342  0.000  0.000  0.000  0.000 {built-in method builtins.getattr}
        5  0.000  0.000  0.000  0.000 {built-in method builtins.hasattr}
       55  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
       33  0.000  0.000  0.000  0.000 {built-in method builtins.len}
      120  0.000  0.000  0.000  0.000 {built-in method builtins.max}
       45  0.000  0.000  0.000  0.000 {built-in method builtins.next}
       16  0.000  0.000  0.000  0.000 {built-in method io.open}
       48  0.000  0.000  0.000  0.000 {built-in method math.floor}
       16  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       16  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        1  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       41  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       16  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
      187  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        3  0.000  0.000  0.000  0.000 {built-in method nt.lstat}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
        7  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
        6  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
       16  0.000  0.000  0.000  0.000 {method '__exit__' of '_io._IOBase' objects}
        3  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
        6  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
       27  71.607  2.652  71.607  2.652 {method 'acquire' of '_thread.lock' objects}
       35  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
        6  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
       16  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
       52  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       16  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
       51  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       36  0.002  0.000  0.004  0.000 {method 'dump' of '_pickle.Pickler' objects}
        6  0.000  0.000  0.000  0.000 {method 'find' of 'str' objects}
       16  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
        4  0.000  0.000  0.000  0.000 {method 'getbuffer' of '_io.BytesIO' objects}
       19  1.522  0.080  1.522  0.080 {method 'index' of 'list' objects}
       32  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
       54  0.000  0.000  0.000  0.000 {method 'join' of 'str' objects}
        3  0.000  0.000  0.000  0.000 {method 'locked' of '_thread.lock' objects}
        3  0.000  0.000  0.000  0.000 {method 'put' of '_queue.SimpleQueue' objects}
       48  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
        9  0.000  0.000  0.000  0.000 {method 'release' of '_thread.lock' objects}
       35  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
       55  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
       32  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
       52  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
        3  0.000  0.000  0.000  0.000 {method 'upper' of 'str' objects}
125250500 84.7045266 None
Enter Password: q
Done
When thinking of how to fix the early termination problems I was learning more about multiprocessor map functions. That is where I thought more about what I really wanted to do, originally I was just trying to emulate the for loop implementation and have it be the exact same. However I realized that by trying to match the for loop implementation exactly would hinder performance. That then lead me to using imap_unordered instead of map which had the benefit of first being unordered which improved performance since I didn't need things to be ordered. Second is that to my knowledge it returned values as quickly as they were processed which added early termination. This implementation also meant that count would be inconsistent since it all depended on how quickly each core could process data, this is when I also started to return the decoded password instead of just count and time to ensure that the password was correctly found. In terms of performance it is now ~55 seconds for the hardest password in the 500 word dictionary of amongamongamong and was the fastest version for a while and is what was used to estimate the time taken in the initial print. In terms of profiler it is still limited by locks.
def decrypt(password, algorithm, p):
    test = "".join([s for s in p]).encode()
    hash = hashlib.new(algorithm)
    hash.update(test)
    if (hash.digest() == password):
        return test
    return None
def imultiHashAttack(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    count = 0
    func = functools.partial(decrypt, password, algorithm)
    pool = multiprocessing.Pool()
    for i in range(1, wordLimit + 1):
        perms = itertools.product(words, repeat=i)
        for value in pool.imap_unordered(func, perms, chunksize=20000):
            count += 1
            if value != None:
                pool.terminate()
                pool.join()
                return count, (time.time_ns() - start) / 1e9, value.decode()
    pool.close()
    pool.join()
    return NoneÂ
Longest Password is amongamongamong and will take around 125250500 iterations and around 75.1503 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
         125348737 function calls in 69.979 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
       55  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        3  0.000  0.000  0.000  0.000 <frozen ntpath>:107(join)
        6  0.000  0.000  0.000  0.000 <frozen ntpath>:154(splitdrive)
       16  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       16  0.000  0.000  0.000  0.000 <frozen ntpath>:87(isabs)
        1  0.000  0.000  69.979  69.979 <string>:1(<module>)
        1  25.197  25.197  69.978  69.978 DicAttack.py:66(imultiHashAttack)
       19  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       19  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        6  0.000  0.000  0.000  0.000 connection.py:118(__init__)
        6  0.000  0.000  0.000  0.000 connection.py:131(__del__)
       67  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
        3  0.000  0.000  0.000  0.000 connection.py:143(_check_writable)
      128  0.000  0.000  0.000  0.000 connection.py:159(readable)
      128  0.000  0.000  0.000  0.000 connection.py:164(writable)
       64  0.000  0.000  0.000  0.000 connection.py:169(fileno)
        3  0.000  0.000  0.000  0.000 connection.py:182(send_bytes)
        6  0.000  0.000  0.000  0.000 connection.py:277(_close)
        3  0.000  0.000  0.000  0.000 connection.py:284(_send_bytes)
        3  0.000  0.000  0.000  0.000 connection.py:552(Pipe)
        3  0.000  0.000  0.000  0.000 connection.py:70(arbitrary_address)
       64  0.000  0.000  0.001  0.000 connection.py:973(reduce_pipe_connection)
        3  0.000  0.000  0.000  0.000 context.py:110(SimpleQueue)
        1  0.000  0.000  0.084  0.084 context.py:115(Pool)
        6  0.000  0.000  0.000  0.000 context.py:187(get_context)
        3  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
        1  0.000  0.000  0.000  0.000 context.py:237(get_context)
       16  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       16  0.000  0.000  0.078  0.005 context.py:333(_Popen)
      160  0.000  0.000  0.000  0.000 context.py:365(get_spawning_popen)
       32  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
       64  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 pool.py:157(__init__)
       16  0.000  0.000  0.001  0.000 pool.py:179(Process)
        1  0.000  0.000  0.084  0.084 pool.py:183(__init__)
        1  0.000  0.000  0.000  0.000 pool.py:266(__del__)
        1  0.000  0.000  0.000  0.000 pool.py:279(_get_sentinels)
        1  0.000  0.000  0.079  0.079 pool.py:305(_repopulate_pool)
        1  0.000  0.000  0.079  0.079 pool.py:314(_repopulate_pool_static)
        1  0.000  0.000  0.000  0.000 pool.py:345(_setup_queues)
        3  0.000  0.000  0.000  0.000 pool.py:351(_check_running)
        3  0.000  0.000  0.000  0.000 pool.py:425(imap_unordered)
125250503 Â 11.825Â Â 0.000 Â 44.571Â Â 0.000 pool.py:451(<genexpr>)
        1  0.000  0.000  0.125  0.125 pool.py:654(terminate)
        1  0.000  0.000  0.000  0.000 pool.py:659(join)
        1  0.000  0.000  0.103  0.103 pool.py:671(_help_stuff_finish)
        1  0.000  0.000  0.125  0.125 pool.py:680(_terminate_pool)
        3  0.000  0.000  0.000  0.000 pool.py:839(__init__)
        3  0.000  0.000  0.000  0.000 pool.py:850(__iter__)
     6266  0.089  0.000  32.747  0.005 pool.py:853(next)
      173  0.001  0.000  0.018  0.000 popen_spawn_win32.py:103(wait)
      152  0.000  0.000  0.001  0.000 popen_spawn_win32.py:121(poll)
       16  0.000  0.000  0.003  0.000 popen_spawn_win32.py:124(terminate)
       16  0.000  0.000  0.001  0.000 popen_spawn_win32.py:29(_close_handles)
       16  0.001  0.000  0.077  0.005 popen_spawn_win32.py:45(__init__)
       80  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
       32  0.000  0.000  0.000  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       16  0.000  0.000  0.078  0.005 process.py:110(start)
       16  0.000  0.000  0.003  0.000 process.py:128(terminate)
       21  0.000  0.000  0.018  0.001 process.py:142(join)
       16  0.000  0.000  0.000  0.000 process.py:153(is_alive)
       32  0.000  0.000  0.000  0.000 process.py:189(name)
       16  0.000  0.000  0.000  0.000 process.py:193(name)
       16  0.000  0.000  0.000  0.000 process.py:205(daemon)
       16  0.000  0.000  0.000  0.000 process.py:213(authkey)
       16  0.000  0.000  0.000  0.000 process.py:224(exitcode)
        5  0.000  0.000  0.000  0.000 process.py:234(ident)
       32  0.000  0.000  0.000  0.000 process.py:350(__reduce__)
       35  0.000  0.000  0.000  0.000 process.py:37(current_process)
       16  0.000  0.000  0.001  0.000 process.py:61(_cleanup)
       16  0.000  0.000  0.000  0.000 process.py:80(__init__)
       32  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
       90  0.000  0.000  0.000  0.000 process.py:99(_check_closed)
        3  0.000  0.000  0.000  0.000 queues.py:339(__init__)
       32  0.000  0.000  0.000  0.000 queues.py:355(__getstate__)
        3  0.000  0.000  0.000  0.000 queues.py:369(put)
        6  0.000  0.000  0.000  0.000 random.py:480(choices)
        6  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
       64  0.000  0.000  0.001  0.000 reduction.py:106(__init__)
       35  0.000  0.000  0.001  0.000 reduction.py:38(__init__)
        3  0.000  0.000  0.000  0.000 reduction.py:48(dumps)
       32  0.000  0.000  0.005  0.000 reduction.py:58(dump)
       32  0.000  0.000  0.000  0.000 reduction.py:71(duplicate)
       16  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       16  0.000  0.000  0.001  0.000 spawn.py:160(get_preparation_data)
       32  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       16  0.000  0.000  0.001  0.000 spawn.py:83(get_command_line)
       48  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       16  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       16  0.000  0.000  0.000  0.000 subprocess.py:300(_args_from_interpreter_flags)
       32  0.000  0.000  0.000  0.000 synchronize.py:100(__getstate__)
        3  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        3  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        3  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        3  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        6  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        6  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        3  0.000  0.000  0.000  0.000 tempfile.py:230(_get_candidate_names)
        3  0.000  0.000  0.000  0.000 tempfile.py:401(mktemp)
        3  0.000  0.000  0.000  0.000 tempfile.py:77(_exists)
        3  0.000  0.000  0.000  0.000 threading.py:1051(_stop)
        6  0.000  0.000  0.000  0.000 threading.py:1087(join)
        8  0.000  0.000  0.000  0.000 threading.py:1125(_wait_for_tstate_lock)
        2  0.000  0.000  0.000  0.000 threading.py:1192(is_alive)
        6  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        3  0.000  0.000  0.000  0.000 threading.py:1221(daemon)
        3  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
       12  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        6  0.000  0.000  0.000  0.000 threading.py:243(__init__)
     6269  0.006  0.000  0.010  0.000 threading.py:271(__enter__)
     6269  0.005  0.000  0.006  0.000 threading.py:274(__exit__)
     4666  0.003  0.000  0.004  0.000 threading.py:280(_release_save)
     4666  0.008  0.000  0.012  0.000 threading.py:283(_acquire_restore)
     4666  0.003  0.000  0.006  0.000 threading.py:286(_is_owned)
     4666  0.035  0.000  32.640  0.007 threading.py:295(wait)
        3  0.000  0.000  0.000  0.000 threading.py:562(__init__)
       14  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        3  0.000  0.000  0.003  0.001 threading.py:611(wait)
        3  0.000  0.000  0.000  0.000 threading.py:811(_newname)
        3  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        3  0.000  0.000  0.004  0.001 threading.py:945(start)
       17  0.000  0.000  0.000  0.000 util.py:189(__init__)
       17  0.000  0.000  0.126  0.007 util.py:208(__call__)
       17  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
       34  0.000  0.000  0.000  0.000 util.py:48(debug)
     4672  0.016  0.000  0.016  0.000 {built-in method _thread.allocate_lock}
       12  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        3  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
      118  0.001  0.000  0.001  0.000 {built-in method _winapi.CloseHandle}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.ConnectNamedPipe}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFile}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateNamedPipe}
       16  0.000  0.000  0.000  0.000 {built-in method _winapi.CreatePipe}
       16  0.069  0.004  0.069  0.004 {built-in method _winapi.CreateProcess}
       96  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
       96  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       16  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
       64  0.000  0.000  0.000  0.000 {built-in method _winapi.OpenProcess}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.SetNamedPipeHandleState}
       16  0.003  0.000  0.003  0.000 {built-in method _winapi.TerminateProcess}
      157  0.018  0.000  0.018  0.000 {built-in method _winapi.WaitForSingleObject}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.WriteFile}
        1  0.000  0.000  69.979  69.979 {built-in method builtins.exec}
      342  0.000  0.000  0.000  0.000 {built-in method builtins.getattr}
        2  0.000  0.000  0.000  0.000 {built-in method builtins.hasattr}
       55  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
       18  0.000  0.000  0.000  0.000 {built-in method builtins.len}
      152  0.000  0.000  0.000  0.000 {built-in method builtins.max}
       45  0.000  0.000  0.000  0.000 {built-in method builtins.next}
       16  0.000  0.000  0.000  0.000 {built-in method io.open}
       48  0.000  0.000  0.000  0.000 {built-in method math.floor}
       16  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       16  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        1  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       41  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       16  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
      192  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        3  0.000  0.000  0.000  0.000 {built-in method nt.lstat}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
        6  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
     6269  0.004  0.000  0.004  0.000 {method '__enter__' of '_thread.lock' objects}
       16  0.000  0.000  0.000  0.000 {method '__exit__' of '_io._IOBase' objects}
        3  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
     6269  0.001  0.000  0.001  0.000 {method '__exit__' of '_thread.lock' objects}
        1  0.103  0.103  0.103  0.103 {method 'acquire' of '_multiprocessing.SemLock' objects}
    18667  32.573  0.002  32.573  0.002 {method 'acquire' of '_thread.lock' objects}
       35  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
     4666  0.001  0.000  0.001  0.000 {method 'append' of 'collections.deque' objects}
       16  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
       51  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       16  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
       51  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       35  0.002  0.000  0.004  0.000 {method 'dump' of '_pickle.Pickler' objects}
        6  0.000  0.000  0.000  0.000 {method 'find' of 'str' objects}
       16  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
        3  0.000  0.000  0.000  0.000 {method 'getbuffer' of '_io.BytesIO' objects}
       16  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       32  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
       54  0.000  0.000  0.000  0.000 {method 'join' of 'str' objects}
        3  0.000  0.000  0.000  0.000 {method 'locked' of '_thread.lock' objects}
    10929  0.004  0.000  0.004  0.000 {method 'popleft' of 'collections.deque' objects}
        3  0.000  0.000  0.000  0.000 {method 'put' of '_queue.SimpleQueue' objects}
       48  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
     4669  0.001  0.000  0.001  0.000 {method 'release' of '_thread.lock' objects}
       35  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
       55  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
       32  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
       51  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
        3  0.000  0.000  0.000  0.000 {method 'upper' of 'str' objects}
125230500 54.1686588 amongamongamong
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
         125351949 function calls in 74.718 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
       55  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        3  0.000  0.000  0.000  0.000 <frozen ntpath>:107(join)
        6  0.000  0.000  0.000  0.000 <frozen ntpath>:154(splitdrive)
       16  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       16  0.000  0.000  0.000  0.000 <frozen ntpath>:87(isabs)
        1  0.000  0.000  74.718  74.718 <string>:1(<module>)
        1  27.055  27.055  74.717  74.717 DicAttack.py:66(imultiHashAttack)
       19  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       19  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        6  0.000  0.000  0.000  0.000 connection.py:118(__init__)
        6  0.000  0.000  0.000  0.000 connection.py:131(__del__)
       67  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
        3  0.000  0.000  0.000  0.000 connection.py:143(_check_writable)
      128  0.000  0.000  0.000  0.000 connection.py:159(readable)
      128  0.000  0.000  0.000  0.000 connection.py:164(writable)
       64  0.000  0.000  0.000  0.000 connection.py:169(fileno)
        3  0.000  0.000  0.000  0.000 connection.py:182(send_bytes)
        6  0.000  0.000  0.000  0.000 connection.py:277(_close)
        3  0.000  0.000  0.000  0.000 connection.py:284(_send_bytes)
        3  0.000  0.000  0.000  0.000 connection.py:552(Pipe)
        3  0.000  0.000  0.000  0.000 connection.py:70(arbitrary_address)
       64  0.000  0.000  0.001  0.000 connection.py:973(reduce_pipe_connection)
        3  0.000  0.000  0.001  0.000 context.py:110(SimpleQueue)
        1  0.000  0.000  0.083  0.083 context.py:115(Pool)
        6  0.000  0.000  0.000  0.000 context.py:187(get_context)
        3  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
        1  0.000  0.000  0.000  0.000 context.py:237(get_context)
       16  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       16  0.000  0.000  0.079  0.005 context.py:333(_Popen)
      160  0.000  0.000  0.000  0.000 context.py:365(get_spawning_popen)
       32  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
       64  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 pool.py:157(__init__)
       16  0.000  0.000  0.001  0.000 pool.py:179(Process)
        1  0.000  0.000  0.083  0.083 pool.py:183(__init__)
        1  0.000  0.000  0.000  0.000 pool.py:266(__del__)
        1  0.000  0.000  0.000  0.000 pool.py:279(_get_sentinels)
        1  0.000  0.000  0.081  0.081 pool.py:305(_repopulate_pool)
        1  0.000  0.000  0.081  0.081 pool.py:314(_repopulate_pool_static)
        1  0.000  0.000  0.000  0.000 pool.py:345(_setup_queues)
        3  0.000  0.000  0.000  0.000 pool.py:351(_check_running)
        3  0.000  0.000  0.000  0.000 pool.py:425(imap_unordered)
125250503 Â 12.432Â Â 0.000 Â 47.516Â Â 0.000 pool.py:451(<genexpr>)
        1  0.000  0.000  0.062  0.062 pool.py:654(terminate)
        1  0.000  0.000  0.000  0.000 pool.py:659(join)
        1  0.000  0.000  0.043  0.043 pool.py:671(_help_stuff_finish)
        1  0.000  0.000  0.062  0.062 pool.py:680(_terminate_pool)
        3  0.000  0.000  0.000  0.000 pool.py:839(__init__)
        3  0.000  0.000  0.000  0.000 pool.py:850(__iter__)
     6266  0.091  0.000  35.084  0.006 pool.py:853(next)
      171  0.000  0.000  0.016  0.000 popen_spawn_win32.py:103(wait)
      152  0.000  0.000  0.001  0.000 popen_spawn_win32.py:121(poll)
       16  0.000  0.000  0.003  0.000 popen_spawn_win32.py:124(terminate)
       16  0.000  0.000  0.001  0.000 popen_spawn_win32.py:29(_close_handles)
       16  0.001  0.000  0.079  0.005 popen_spawn_win32.py:45(__init__)
       80  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
       32  0.000  0.000  0.000  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       16  0.000  0.000  0.080  0.005 process.py:110(start)
       16  0.000  0.000  0.003  0.000 process.py:128(terminate)
       19  0.000  0.000  0.015  0.001 process.py:142(join)
       16  0.000  0.000  0.000  0.000 process.py:153(is_alive)
       32  0.000  0.000  0.000  0.000 process.py:189(name)
       16  0.000  0.000  0.000  0.000 process.py:193(name)
       16  0.000  0.000  0.000  0.000 process.py:205(daemon)
       16  0.000  0.000  0.000  0.000 process.py:213(authkey)
       16  0.000  0.000  0.000  0.000 process.py:224(exitcode)
        3  0.000  0.000  0.000  0.000 process.py:234(ident)
       32  0.000  0.000  0.001  0.000 process.py:350(__reduce__)
       35  0.000  0.000  0.000  0.000 process.py:37(current_process)
       16  0.000  0.000  0.001  0.000 process.py:61(_cleanup)
       16  0.000  0.000  0.000  0.000 process.py:80(__init__)
       32  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
       86  0.000  0.000  0.000  0.000 process.py:99(_check_closed)
        3  0.000  0.000  0.001  0.000 queues.py:339(__init__)
       32  0.000  0.000  0.000  0.000 queues.py:355(__getstate__)
        3  0.000  0.000  0.000  0.000 queues.py:369(put)
        6  0.000  0.000  0.000  0.000 random.py:480(choices)
        6  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
       64  0.000  0.000  0.001  0.000 reduction.py:106(__init__)
       35  0.000  0.000  0.001  0.000 reduction.py:38(__init__)
        3  0.000  0.000  0.000  0.000 reduction.py:48(dumps)
       32  0.000  0.000  0.005  0.000 reduction.py:58(dump)
       32  0.000  0.000  0.000  0.000 reduction.py:71(duplicate)
       16  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       16  0.000  0.000  0.001  0.000 spawn.py:160(get_preparation_data)
       32  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       16  0.000  0.000  0.001  0.000 spawn.py:83(get_command_line)
       48  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       16  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       16  0.000  0.000  0.000  0.000 subprocess.py:300(_args_from_interpreter_flags)
       32  0.000  0.000  0.000  0.000 synchronize.py:100(__getstate__)
        3  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        3  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        3  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        3  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        6  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        6  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        3  0.000  0.000  0.000  0.000 tempfile.py:230(_get_candidate_names)
        3  0.000  0.000  0.000  0.000 tempfile.py:401(mktemp)
        3  0.000  0.000  0.000  0.000 tempfile.py:77(_exists)
        3  0.000  0.000  0.000  0.000 threading.py:1051(_stop)
        6  0.000  0.000  0.000  0.000 threading.py:1087(join)
        8  0.000  0.000  0.000  0.000 threading.py:1125(_wait_for_tstate_lock)
        2  0.000  0.000  0.000  0.000 threading.py:1192(is_alive)
        6  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        3  0.000  0.000  0.000  0.000 threading.py:1221(daemon)
        3  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
       12  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        6  0.000  0.000  0.000  0.000 threading.py:243(__init__)
     6269  0.007  0.000  0.012  0.000 threading.py:271(__enter__)
     6269  0.005  0.000  0.006  0.000 threading.py:274(__exit__)
     4935  0.004  0.000  0.004  0.000 threading.py:280(_release_save)
     4935  0.008  0.000  0.012  0.000 threading.py:283(_acquire_restore)
     4935  0.004  0.000  0.007  0.000 threading.py:286(_is_owned)
     4935  0.046  0.000  34.972  0.007 threading.py:295(wait)
        3  0.000  0.000  0.000  0.000 threading.py:562(__init__)
       14  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        3  0.000  0.000  0.001  0.000 threading.py:611(wait)
        3  0.000  0.000  0.000  0.000 threading.py:811(_newname)
        3  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        3  0.000  0.000  0.001  0.000 threading.py:945(start)
       17  0.000  0.000  0.000  0.000 util.py:189(__init__)
       17  0.000  0.000  0.063  0.004 util.py:208(__call__)
       17  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
       32  0.000  0.000  0.000  0.000 util.py:48(debug)
     4941  0.017  0.000  0.017  0.000 {built-in method _thread.allocate_lock}
       12  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        3  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
      118  0.001  0.000  0.001  0.000 {built-in method _winapi.CloseHandle}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.ConnectNamedPipe}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFile}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateNamedPipe}
       16  0.000  0.000  0.000  0.000 {built-in method _winapi.CreatePipe}
       16  0.070  0.004  0.070  0.004 {built-in method _winapi.CreateProcess}
       96  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
       96  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       16  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
       64  0.000  0.000  0.000  0.000 {built-in method _winapi.OpenProcess}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.SetNamedPipeHandleState}
       16  0.003  0.000  0.003  0.000 {built-in method _winapi.TerminateProcess}
      155  0.015  0.000  0.015  0.000 {built-in method _winapi.WaitForSingleObject}
        3  0.000  0.000  0.000  0.000 {built-in method _winapi.WriteFile}
        1  0.000  0.000  74.718  74.718 {built-in method builtins.exec}
      342  0.000  0.000  0.000  0.000 {built-in method builtins.getattr}
        2  0.000  0.000  0.000  0.000 {built-in method builtins.hasattr}
       55  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
       18  0.000  0.000  0.000  0.000 {built-in method builtins.len}
      152  0.000  0.000  0.000  0.000 {built-in method builtins.max}
       45  0.000  0.000  0.000  0.000 {built-in method builtins.next}
       16  0.000  0.000  0.000  0.000 {built-in method io.open}
       48  0.000  0.000  0.000  0.000 {built-in method math.floor}
       16  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       16  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        1  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       41  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       16  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
      190  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        3  0.000  0.000  0.000  0.000 {built-in method nt.lstat}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
        6  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
     6269  0.005  0.000  0.005  0.000 {method '__enter__' of '_thread.lock' objects}
       16  0.000  0.000  0.000  0.000 {method '__exit__' of '_io._IOBase' objects}
        3  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
     6269  0.001  0.000  0.001  0.000 {method '__exit__' of '_thread.lock' objects}
        1  0.042  0.042  0.042  0.042 {method 'acquire' of '_multiprocessing.SemLock' objects}
    19743  34.890  0.002  34.890  0.002 {method 'acquire' of '_thread.lock' objects}
       35  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
     4935  0.001  0.000  0.001  0.000 {method 'append' of 'collections.deque' objects}
       16  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
       51  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       16  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
       51  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       35  0.002  0.000  0.004  0.000 {method 'dump' of '_pickle.Pickler' objects}
        6  0.000  0.000  0.000  0.000 {method 'find' of 'str' objects}
       16  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
        3  0.000  0.000  0.000  0.000 {method 'getbuffer' of '_io.BytesIO' objects}
       16  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       32  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
       54  0.000  0.000  0.000  0.000 {method 'join' of 'str' objects}
        3  0.000  0.000  0.000  0.000 {method 'locked' of '_thread.lock' objects}
    11198  0.005  0.000  0.005  0.000 {method 'popleft' of 'collections.deque' objects}
        3  0.000  0.000  0.000  0.000 {method 'put' of '_queue.SimpleQueue' objects}
       48  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
     4938  0.001  0.000  0.001  0.000 {method 'release' of '_thread.lock' objects}
       35  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
       55  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
       32  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
       51  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
        3  0.000  0.000  0.000  0.000 {method 'upper' of 'str' objects}
125250500 57.5101229 amongamongamong
Enter Password: q
Done
Since the bottleneck for a Pool was locks then the idea was to not use a pool but instead make my own. However this ended up making my code very messy since I had to use a queue to store my data instead. Although the code could probably be improved, for example the sleep could be removed, however the current bottleneck is method 'dump' of '_pickle.Pickler' objects which a quick Google search cites Windows being unable to spawn many processes as the problem. In terms of performance it is ~100 seconds for the hardest password in the 500 word dictionary of amongamongamong.
def multiDecrypt(perm, password, algorithm, queue):
    count = 0
    for p in perm:
        count += 1
        test = "".join([s for s in p]).encode()
        hash = hashlib.new(algorithm)
        hash.update(test)
        if (hash.digest() == password):
            ret = queue.get()
            ret['item'] = test
            ret['found'] = True
            ret['count'] = ret['count'] + count
            queue.put(ret)
            return
    ret = queue.get()
    ret['count'] = ret['count'] + count
    queue.put(ret)
def multiProcess(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    queue = multiprocessing.Queue()
    queue.put({'item' : -1, 'found' : False, 'count' : 0})
    for i in range(1, wordLimit + 1):
        perms = list(itertools.product(words, repeat=i))
        size = int(len(perms) / multiprocessing.cpu_count())
        processes = []
        for s in range(0, len(perms), size):
            p = multiprocessing.Process(target=multiDecrypt, args=(perms[s : s + size], password, algorithm, queue))
            processes.append(p)
            p.start()
        while True:
            ret = queue.get()
            check = ret['found']
            queue.put(ret)
            if check:
                break
            else:
                check = True
            for p in processes:
                if p.is_alive():
                    check = False
                    break
            if check:
                break
            else:
                time.sleep(1) Â
        for p in processes:
            if p.is_alive():
                p.terminate()
            p.join()
        ret = queue.get()
        if (ret['found']):
            return ret['count'], (time.time_ns() - start) / 1e9, ret['item'].decode()
        else:
            queue.put(ret)
    return NoneÂ
Longest Password is amongamongamong and will take around 125250500 iterations and around 75.1503 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
         11943 function calls in 101.580 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
      151  0.000  0.000  0.001  0.000 <frozen importlib._bootstrap>:405(parent)
        1  0.000  0.000  0.000  0.000 <frozen ntpath>:107(join)
        2  0.000  0.000  0.000  0.000 <frozen ntpath>:154(splitdrive)
       49  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       49  0.000  0.000  0.001  0.000 <frozen ntpath>:87(isabs)
        1  5.062  5.062 101.579 101.579 <string>:1(<module>)
        1  13.051  13.051  96.516  96.516 DicAttack.py:101(multiProcess)
       49  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       50  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        2  0.000  0.000  0.000  0.000 connection.py:118(__init__)
      119  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
       21  0.000  0.000  0.000  0.000 connection.py:139(_check_readable)
      196  0.000  0.000  0.000  0.000 connection.py:159(readable)
      196  0.000  0.000  0.000  0.000 connection.py:164(writable)
       98  0.000  0.000  0.000  0.000 connection.py:169(fileno)
       21  0.000  0.000  0.002  0.000 connection.py:208(recv_bytes)
       21  0.000  0.000  0.001  0.000 connection.py:310(_recv_bytes)
        1  0.000  0.000  0.002  0.002 connection.py:552(Pipe)
        1  0.001  0.001  0.002  0.002 connection.py:70(arbitrary_address)
       98  0.001  0.000  0.003  0.000 connection.py:973(reduce_pipe_connection)
        1  0.000  0.000  0.003  0.003 context.py:100(Queue)
        2  0.000  0.000  0.000  0.000 context.py:187(get_context)
        2  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
       49  0.000  0.000  66.958  1.366 context.py:222(_Popen)
       50  0.000  0.000  0.000  0.000 context.py:237(get_context)
       49  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       49  0.001  0.000  66.958  1.366 context.py:333(_Popen)
      441  0.000  0.000  0.000  0.000 context.py:365(get_spawning_popen)
       98  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
      147  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
        1  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 context.py:85(BoundedSemaphore)
      567  0.001  0.000  0.002  0.000 popen_spawn_win32.py:103(wait)
      518  0.000  0.000  0.002  0.000 popen_spawn_win32.py:121(poll)
       49  0.000  0.000  0.004  0.000 popen_spawn_win32.py:29(_close_handles)
       49  0.003  0.000  66.956  1.366 popen_spawn_win32.py:45(__init__)
      245  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
       98  0.000  0.000  0.000  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       49  1.485  0.030  68.445  1.397 process.py:110(start)
       49  0.000  0.000  0.000  0.000 process.py:142(join)
      292  0.001  0.000  0.002  0.000 process.py:153(is_alive)
       49  0.000  0.000  0.000  0.000 process.py:189(name)
       49  0.000  0.000  0.000  0.000 process.py:213(authkey)
       98  0.001  0.000  0.001  0.000 process.py:350(__reduce__)
      100  0.000  0.000  0.000  0.000 process.py:37(current_process)
       49  0.001  0.000  0.002  0.000 process.py:61(_cleanup)
       49  0.002  0.000  0.002  0.000 process.py:80(__init__)
       98  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
      390  0.000  0.000  0.000  0.000 process.py:99(_check_closed)
        1  0.000  0.000  0.001  0.001 queues.py:161(_start_thread)
        1  0.000  0.000  0.000  0.000 queues.py:204(_finalize_close)
        1  0.000  0.000  0.003  0.003 queues.py:37(__init__)
       49  0.000  0.000  0.001  0.000 queues.py:57(__getstate__)
        1  0.000  0.000  0.000  0.000 queues.py:71(_reset)
       21  0.000  0.000  0.002  0.000 queues.py:86(put)
       21  0.001  0.000  0.003  0.000 queues.py:98(get)
        3  0.000  0.000  0.000  0.000 random.py:480(choices)
        3  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
       98  0.000  0.000  0.001  0.000 reduction.py:106(__init__)
       98  0.001  0.000  0.001  0.000 reduction.py:38(__init__)
       98  3.978  0.041  65.231  0.666 reduction.py:58(dump)
       98  0.000  0.000  0.000  0.000 reduction.py:71(duplicate)
       49  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       49  0.001  0.000  0.003  0.000 spawn.py:160(get_preparation_data)
       98  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       49  0.001  0.000  0.002  0.000 spawn.py:83(get_command_line)
      147  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       49  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       49  0.001  0.000  0.001  0.000 subprocess.py:300(_args_from_interpreter_flags)
       98  0.000  0.000  0.001  0.000 synchronize.py:100(__getstate__)
        2  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        1  0.000  0.000  0.000  0.000 synchronize.py:151(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        2  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        2  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
       21  0.000  0.000  0.000  0.000 synchronize.py:94(__enter__)
       21  0.000  0.000  0.000  0.000 synchronize.py:97(__exit__)
        3  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        3  0.000  0.000  0.001  0.000 tempfile.py:154(__next__)
        1  0.000  0.000  0.000  0.000 tempfile.py:230(_get_candidate_names)
        1  0.000  0.000  0.002  0.002 tempfile.py:401(mktemp)
        1  0.000  0.000  0.000  0.000 tempfile.py:77(_exists)
        1  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        1  0.000  0.000  0.000  0.000 threading.py:1221(daemon)
        1  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
        1  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        2  0.000  0.000  0.000  0.000 threading.py:243(__init__)
       23  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
       23  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
        1  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
        1  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
       23  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
        1  0.000  0.000  0.000  0.000 threading.py:295(wait)
       22  0.000  0.000  0.000  0.000 threading.py:366(notify)
        1  0.000  0.000  0.000  0.000 threading.py:562(__init__)
        2  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        1  0.000  0.000  0.001  0.001 threading.py:611(wait)
        1  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        1  0.000  0.000  0.001  0.001 threading.py:945(start)
       51  0.001  0.000  0.001  0.000 util.py:189(__init__)
       50  0.000  0.000  0.004  0.000 util.py:208(__call__)
       50  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
        6  0.000  0.000  0.000  0.000 util.py:48(debug)
       21  0.000  0.000  0.000  0.000 {built-in method _pickle.loads}
        3  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
      245  0.004  0.000  0.004  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.ConnectNamedPipe}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFile}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateNamedPipe}
       49  0.002  0.000  0.002  0.000 {built-in method _winapi.CreatePipe}
       49  1.711  0.035  1.711  0.035 {built-in method _winapi.CreateProcess}
      196  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
      196  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       49  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
       98  0.001  0.000  0.001  0.000 {built-in method _winapi.OpenProcess}
       21  0.000  0.000  0.000  0.000 {built-in method _winapi.ReadFile}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.SetNamedPipeHandleState}
        2  0.000  0.000  0.000  0.000 {built-in method _winapi.WaitForMultipleObjects}
      265  0.001  0.000  0.001  0.000 {built-in method _winapi.WaitForSingleObject}
        1  0.001  0.001 101.580 101.580 {built-in method builtins.exec}
      983  0.001  0.000  0.001  0.000 {built-in method builtins.getattr}
      102  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
       11  0.000  0.000  0.000  0.000 {built-in method builtins.len}
      265  0.000  0.000  0.000  0.000 {built-in method builtins.max}
      104  0.000  0.000  0.001  0.000 {built-in method builtins.next}
       49  0.001  0.000  0.001  0.000 {built-in method io.open}
       24  0.000  0.000  0.000  0.000 {built-in method math.floor}
       49  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       49  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
      101  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       49  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
      692  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.lstat}
       15  15.005  1.000  15.005  1.000 {built-in method time.sleep}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
       22  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
       21  0.000  0.000  0.000  0.000 {method '__enter__' of '_multiprocessing.SemLock' objects}
       23  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
       49  0.002  0.000  0.002  0.000 {method '__exit__' of '_io._IOBase' objects}
       21  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
       23  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
       21  0.000  0.000  0.000  0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
       26  0.000  0.000  0.000  0.000 {method 'acquire' of '_thread.lock' objects}
       99  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       23  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
       49  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'clear' of 'collections.deque' objects}
      147  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       49  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
      400  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       98  61.246  0.625  61.252  0.625 {method 'dump' of '_pickle.Pickler' objects}
        2  0.000  0.000  0.000  0.000 {method 'find' of 'str' objects}
       49  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
       21  0.000  0.000  0.000  0.000 {method 'getbuffer' of '_winapi.Overlapped' objects}
       21  0.000  0.000  0.000  0.000 {method 'getvalue' of '_io.BytesIO' objects}
       49  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       98  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
      150  0.000  0.000  0.001  0.000 {method 'join' of 'str' objects}
       24  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
       21  0.000  0.000  0.000  0.000 {method 'release' of '_multiprocessing.SemLock' objects}
       22  0.000  0.000  0.000  0.000 {method 'release' of '_thread.lock' objects}
       21  0.000  0.000  0.000  0.000 {method 'remove' of 'collections.deque' objects}
       50  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
      151  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
       98  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
      147  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
        1  0.000  0.000  0.000  0.000 {method 'upper' of 'str' objects}
       21  0.000  0.000  0.000  0.000 {method 'write' of '_io.BytesIO' objects}
125250500 100.2815231 amongamongamong
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
         12304 function calls in 108.210 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
      151  0.000  0.000  0.001  0.000 <frozen importlib._bootstrap>:405(parent)
        1  0.000  0.000  0.000  0.000 <frozen ntpath>:107(join)
        2  0.000  0.000  0.000  0.000 <frozen ntpath>:154(splitdrive)
       49  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       49  0.000  0.000  0.001  0.000 <frozen ntpath>:87(isabs)
        1  6.644  6.644 108.209 108.209 <string>:1(<module>)
        1  13.012  13.012 101.564 101.564 DicAttack.py:101(multiProcess)
       49  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       50  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        2  0.000  0.000  0.000  0.000 connection.py:118(__init__)
      122  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
       24  0.000  0.000  0.000  0.000 connection.py:139(_check_readable)
      196  0.000  0.000  0.000  0.000 connection.py:159(readable)
      196  0.000  0.000  0.000  0.000 connection.py:164(writable)
       98  0.000  0.000  0.000  0.000 connection.py:169(fileno)
       24  0.000  0.000  0.002  0.000 connection.py:208(recv_bytes)
       24  0.001  0.000  0.002  0.000 connection.py:310(_recv_bytes)
        1  0.000  0.000  0.001  0.001 connection.py:552(Pipe)
        1  0.000  0.000  0.001  0.001 connection.py:70(arbitrary_address)
       98  0.001  0.000  0.003  0.000 connection.py:973(reduce_pipe_connection)
        1  0.000  0.000  0.002  0.002 context.py:100(Queue)
        2  0.000  0.000  0.000  0.000 context.py:187(get_context)
        2  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
       49  0.000  0.000  68.734  1.403 context.py:222(_Popen)
       50  0.000  0.000  0.000  0.000 context.py:237(get_context)
       49  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       49  0.001  0.000  68.734  1.403 context.py:333(_Popen)
      441  0.000  0.000  0.001  0.000 context.py:365(get_spawning_popen)
       98  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
      147  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
        1  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 context.py:85(BoundedSemaphore)
      614  0.001  0.000  0.002  0.000 popen_spawn_win32.py:103(wait)
      565  0.000  0.000  0.003  0.000 popen_spawn_win32.py:121(poll)
       49  0.000  0.000  0.003  0.000 popen_spawn_win32.py:29(_close_handles)
       49  0.003  0.000  68.732  1.403 popen_spawn_win32.py:45(__init__)
      245  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
       98  0.000  0.000  0.001  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       49  1.795  0.037  70.531  1.439 process.py:110(start)
       49  0.000  0.000  0.000  0.000 process.py:142(join)
      333  0.001  0.000  0.002  0.000 process.py:153(is_alive)
       49  0.000  0.000  0.000  0.000 process.py:189(name)
       49  0.000  0.000  0.000  0.000 process.py:213(authkey)
       98  0.001  0.000  0.002  0.000 process.py:350(__reduce__)
      100  0.000  0.000  0.000  0.000 process.py:37(current_process)
       49  0.001  0.000  0.002  0.000 process.py:61(_cleanup)
       49  0.002  0.000  0.003  0.000 process.py:80(__init__)
       98  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
      431  0.000  0.000  0.000  0.000 process.py:99(_check_closed)
        1  0.000  0.000  0.001  0.001 queues.py:161(_start_thread)
        1  0.000  0.000  0.000  0.000 queues.py:204(_finalize_close)
        1  0.000  0.000  0.001  0.001 queues.py:37(__init__)
       49  0.000  0.000  0.001  0.000 queues.py:57(__getstate__)
        1  0.000  0.000  0.000  0.000 queues.py:71(_reset)
       24  0.000  0.000  0.002  0.000 queues.py:86(put)
       24  0.001  0.000  0.003  0.000 queues.py:98(get)
        3  0.000  0.000  0.000  0.000 random.py:480(choices)
        3  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
       98  0.000  0.000  0.002  0.000 reduction.py:106(__init__)
       98  0.001  0.000  0.002  0.000 reduction.py:38(__init__)
       98  4.178  0.043  68.516  0.699 reduction.py:58(dump)
       98  0.000  0.000  0.000  0.000 reduction.py:71(duplicate)
       49  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       49  0.001  0.000  0.003  0.000 spawn.py:160(get_preparation_data)
       98  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       49  0.001  0.000  0.003  0.000 spawn.py:83(get_command_line)
      147  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       49  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       49  0.001  0.000  0.001  0.000 subprocess.py:300(_args_from_interpreter_flags)
       98  0.000  0.000  0.001  0.000 synchronize.py:100(__getstate__)
        2  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        1  0.000  0.000  0.000  0.000 synchronize.py:151(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        2  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        2  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
       24  0.000  0.000  0.000  0.000 synchronize.py:94(__enter__)
       24  0.000  0.000  0.000  0.000 synchronize.py:97(__exit__)
        3  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        3  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        1  0.000  0.000  0.000  0.000 tempfile.py:230(_get_candidate_names)
        1  0.000  0.000  0.001  0.001 tempfile.py:401(mktemp)
        1  0.000  0.000  0.000  0.000 tempfile.py:77(_exists)
        1  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        1  0.000  0.000  0.000  0.000 threading.py:1221(daemon)
        1  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
        1  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        2  0.000  0.000  0.000  0.000 threading.py:243(__init__)
       26  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
       26  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
        1  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
        1  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
       26  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
        1  0.000  0.000  0.000  0.000 threading.py:295(wait)
       25  0.000  0.000  0.001  0.000 threading.py:366(notify)
        1  0.000  0.000  0.000  0.000 threading.py:562(__init__)
        2  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        1  0.000  0.000  0.000  0.000 threading.py:611(wait)
        1  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        1  0.000  0.000  0.001  0.001 threading.py:945(start)
       51  0.001  0.000  0.001  0.000 util.py:189(__init__)
       50  0.000  0.000  0.004  0.000 util.py:208(__call__)
       50  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
        6  0.000  0.000  0.000  0.000 util.py:48(debug)
       24  0.000  0.000  0.000  0.000 {built-in method _pickle.loads}
        3  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
      245  0.003  0.000  0.003  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.ConnectNamedPipe}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFile}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateNamedPipe}
       49  0.002  0.000  0.002  0.000 {built-in method _winapi.CreatePipe}
       49  0.201  0.004  0.201  0.004 {built-in method _winapi.CreateProcess}
      196  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
      196  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       49  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
       98  0.001  0.000  0.001  0.000 {built-in method _winapi.OpenProcess}
       24  0.001  0.000  0.001  0.000 {built-in method _winapi.ReadFile}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.SetNamedPipeHandleState}
        3  0.001  0.000  0.001  0.000 {built-in method _winapi.WaitForMultipleObjects}
      274  0.001  0.000  0.001  0.000 {built-in method _winapi.WaitForSingleObject}
        1  0.001  0.001 108.210 108.210 {built-in method builtins.exec}
      983  0.001  0.000  0.001  0.000 {built-in method builtins.getattr}
      102  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
       11  0.000  0.000  0.000  0.000 {built-in method builtins.len}
      274  0.000  0.000  0.000  0.000 {built-in method builtins.max}
      104  0.000  0.000  0.000  0.000 {built-in method builtins.next}
       49  0.002  0.000  0.002  0.000 {built-in method io.open}
       24  0.000  0.000  0.000  0.000 {built-in method math.floor}
       49  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       49  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
      101  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       49  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
      733  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.lstat}
       18  18.006  1.000  18.006  1.000 {built-in method time.sleep}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
       25  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
       24  0.000  0.000  0.000  0.000 {method '__enter__' of '_multiprocessing.SemLock' objects}
       26  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
       49  0.002  0.000  0.002  0.000 {method '__exit__' of '_io._IOBase' objects}
       24  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
       26  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
       24  0.000  0.000  0.000  0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
       29  0.000  0.000  0.000  0.000 {method 'acquire' of '_thread.lock' objects}
       99  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       26  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
       49  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'clear' of 'collections.deque' objects}
      147  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       49  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
      438  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       98  64.331  0.656  64.337  0.657 {method 'dump' of '_pickle.Pickler' objects}
        2  0.000  0.000  0.000  0.000 {method 'find' of 'str' objects}
       49  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
       24  0.000  0.000  0.000  0.000 {method 'getbuffer' of '_winapi.Overlapped' objects}
       24  0.000  0.000  0.000  0.000 {method 'getvalue' of '_io.BytesIO' objects}
       49  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       98  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
      150  0.000  0.000  0.001  0.000 {method 'join' of 'str' objects}
       24  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
       24  0.000  0.000  0.000  0.000 {method 'release' of '_multiprocessing.SemLock' objects}
       25  0.000  0.000  0.000  0.000 {method 'release' of '_thread.lock' objects}
       24  0.000  0.000  0.000  0.000 {method 'remove' of 'collections.deque' objects}
       50  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
      151  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
       98  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
      147  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
        1  0.000  0.000  0.000  0.000 {method 'upper' of 'str' objects}
       24  0.000  0.000  0.000  0.000 {method 'write' of '_io.BytesIO' objects}
125250500 97.0823214 amongamongamong
Enter Password: q
Done
Since the bottleneck seemed to be Processes then what if I didn't use Processes but instead Threads. Thus after many iterations I am left with the following code. Although it may not be perfect the longest total time is in the hashing function meaning that my code is taking the longest rather then something else which has happened. For example sleep originally took the longest, that got fixed then _winapi.WaitForMultipleObjects took the longest and when that was fixed it was threading.is_alive. However now it is simply how long it takes to test all permutations. In terms of performance it is ~190 seconds for the hardest password in the 500 word dictionary of amongamongamong.
def multiStopDecrypt(perm, password, algorithm, arr, lock, stop, running):
    count = 0
    for p in perm:
        count += 1
        test = "".join([s for s in p]).encode()
        hash = hashlib.new(algorithm)
        hash.update(test)
        if (hash.digest() == password):
            lock.acquire()
            arr[2] = test
            arr[1] = True
            arr[0] = arr[0] + count
            running[0] = running[0] + 1
            lock.release()
            return
    lock.acquire()
    arr[0] = arr[0] + count
    running[0] = running[0] + 1
    lock.release()
def multiThread(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    stop_threads = False
    arr = [0, False, -1]
    lock = threading.Lock()
    for i in range(1, wordLimit + 1):
        perms = list(itertools.product(words, repeat=i))
        size = int(len(perms) / multiprocessing.cpu_count())
        processes = []
        running = [0]
        for s in range(0, len(perms), size):
            p = threading.Thread(target=multiStopDecrypt, args=(perms[s : s + size], password, algorithm, arr, lock, lambda: stop_threads, running))
            processes.append(p)
            p.start()
        while running[0] != len(processes):
            lock.acquire()
            check = arr[1]
            lock.release()
            if check:
                stop_threads = True
                break
        for p in processes:
            p.join()
        if (arr[1]):
            return arr[0], (time.time_ns() - start) / 1e9, arr[2].decode()
    return NoneÂ
Longest Password is amongamongamong and will take around 125250500 iterations and around 75.1503 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
         48353595 function calls in 198.989 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
        1  3.018  3.018 198.988 198.988 <string>:1(<module>)
        1 185.330 185.330 195.970 195.970 DicAttack.py:160(multiThread)
       49  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       49  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
       49  0.000  0.000  0.000  0.000 threading.py:1051(_stop)
       49  0.000  0.000  3.110  0.063 threading.py:1087(join)
       49  0.000  0.000  3.109  0.063 threading.py:1125(_wait_for_tstate_lock)
       98  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
       49  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
       98  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
       49  0.001  0.000  0.001  0.000 threading.py:243(__init__)
       49  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
       49  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
       49  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
       49  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
       49  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
       49  0.000  0.000  4.115  0.084 threading.py:295(wait)
       49  0.000  0.000  0.001  0.000 threading.py:562(__init__)
       98  0.000  0.000  0.000  0.000 threading.py:575(is_set)
       49  0.001  0.000  4.116  0.084 threading.py:611(wait)
       49  0.000  0.000  0.000  0.000 threading.py:811(_newname)
       49  0.000  0.000  0.000  0.000 threading.py:829(_maintain_shutdown_locks)
       49  0.000  0.000  0.000  0.000 threading.py:839(<listcomp>)
       49  0.001  0.000  0.003  0.000 threading.py:856(__init__)
       49  0.000  0.000  4.118  0.084 threading.py:945(start)
       99  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
       98  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
       49  0.002  0.000  0.002  0.000 {built-in method _thread.start_new_thread}
        1  0.001  0.001 198.989 198.989 {built-in method builtins.exec}
 16117059  0.750  0.000  0.750  0.000 {built-in method builtins.len}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
       49  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
       49  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
       98  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
 16117296  8.947  0.000  8.947  0.000 {method 'acquire' of '_thread.lock' objects}
       49  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       49  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
       49  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
       49  0.000  0.000  0.000  0.000 {method 'difference_update' of 'set' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
       49  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
      116  0.000  0.000  0.000  0.000 {method 'locked' of '_thread.lock' objects}
 16117149  0.934  0.000  0.934  0.000 {method 'release' of '_thread.lock' objects}
125250500 181.8916218 amongamongamong
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
         61462469 function calls in 202.207 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
        1  2.997  2.997 202.206 202.206 <string>:1(<module>)
        1 188.869 188.869 199.209 199.209 DicAttack.py:160(multiThread)
       49  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       49  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
       49  0.000  0.000  0.000  0.000 threading.py:1051(_stop)
       49  0.000  0.000  0.474  0.010 threading.py:1087(join)
       49  0.000  0.000  0.473  0.010 threading.py:1125(_wait_for_tstate_lock)
       98  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
       49  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
       98  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
       49  0.001  0.000  0.001  0.000 threading.py:243(__init__)
       49  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
       49  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
       49  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
       49  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
       49  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
       49  0.001  0.000  4.985  0.102 threading.py:295(wait)
       49  0.000  0.000  0.001  0.000 threading.py:562(__init__)
       98  0.000  0.000  0.000  0.000 threading.py:575(is_set)
       49  0.000  0.000  4.985  0.102 threading.py:611(wait)
       49  0.000  0.000  0.000  0.000 threading.py:811(_newname)
       49  0.000  0.000  0.000  0.000 threading.py:829(_maintain_shutdown_locks)
       49  0.000  0.000  0.000  0.000 threading.py:839(<listcomp>)
       49  0.001  0.000  0.003  0.000 threading.py:856(__init__)
       49  0.000  0.000  4.988  0.102 threading.py:945(start)
       99  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
       98  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
       49  0.002  0.000  0.002  0.000 {built-in method _thread.start_new_thread}
        1  0.001  0.001 202.207 202.207 {built-in method builtins.exec}
 20486674  0.850  0.000  0.850  0.000 {built-in method builtins.len}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
       49  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
       49  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
       98  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
 20486911  8.427  0.000  8.427  0.000 {method 'acquire' of '_thread.lock' objects}
       49  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       49  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
       49  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
       49  0.000  0.000  0.000  0.000 {method 'difference_update' of 'set' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
       49  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
      145  0.000  0.000  0.000  0.000 {method 'locked' of '_thread.lock' objects}
 20486764  1.055  0.000  1.055  0.000 {method 'release' of '_thread.lock' objects}
125250500 203.1789594 amongamongamong
Enter Password: q
Done
Since having several processors and managing them myself seemed the most promising then I went back to that idea. However this time I opted to test pickle's dump on my own which gave me the insight that the thing that was slow was lists. Thus I removed the list and instead passed a itertools.product iterator for the previous permutations and a subsection of the words list. Now in the running function I append each word to the previous permutations to be able to test all permutations. This combined with other smaller optimizations made it so that I finally have a new fastest time of ~30 seconds for the hardest password in the 500 word dictionary of amongamongamong. In terms of profiler everything is roughly the same with no big times, thus the next optimization is probably having a better way of testing if every processor is done since that is around 5 seconds of time.
def run(perms, arr, algorithm, password, words, lock):
    count = 0
    for p in perms:
        for w in words:
            count += 1
            word = "".join(list(p) + [w]).encode()
            hash = hashlib.new(algorithm)
            hash.update(word)
            if hash.digest() == password:
                with lock:
                    arr[2] = word
                    arr[0] = arr[0] + count
                    arr[1] = True
                return
    with lock:
        arr[0] = arr[0] + count
def multiProcessor2(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    arr = shared_memory.ShareableList([0, False, "\0" * 100])
    lock = multiprocessing.Lock()
    for i in range(1, wordLimit + 1):
        perms = itertools.product(words, repeat=i - 1)
        wordsLen = len(words)
        size = math.ceil(wordsLen / multiprocessing.cpu_count())
        processes = []
        for j in range(0, wordsLen, size):
            p = multiprocessing.Process(target=run,args=[perms, arr, algorithm, password, words[j : j + size], lock])
            p.start()
            processes.append(p)
        while not arr[1] and len(processes) != 0:
            processes = list(filter(lambda p: p.is_alive(), processes))
        for p in processes:
            p.terminate()
            p.join()
        if arr[1]:
            break
    return arr[0], (time.time_ns() - start) / 1e9, arr[2].decode()Â
Longest Password is amongamongamong and will take around 125250500 iterations and around 75.1503 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
         25819565 function calls in 24.826 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
      145  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       48  0.000  0.000  0.001  0.000 <frozen ntpath>:87(isabs)
        1  0.000  0.000  24.826  24.826 <string>:1(<module>)
        1  1.539  1.539  24.824  24.824 MultiProcessor2.py:36(multiProcessor2)
  2772852  1.546  0.000  17.086  0.000 MultiProcessor2.py:50(<lambda>)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        1  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
       48  0.000  0.000  3.141  0.065 context.py:222(_Popen)
       49  0.000  0.000  0.000  0.000 context.py:237(get_context)
       48  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       48  0.001  0.000  3.141  0.065 context.py:333(_Popen)
      240  0.000  0.000  0.000  0.000 context.py:365(get_spawning_popen)
       96  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
       48  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
        1  0.000  0.000  0.000  0.000 context.py:65(Lock)
  2773188  5.008  0.000  8.214  0.000 popen_spawn_win32.py:103(wait)
  2773172  1.587  0.000  9.627  0.000 popen_spawn_win32.py:121(poll)
       16  0.000  0.000  0.004  0.000 popen_spawn_win32.py:124(terminate)
       48  0.000  0.000  0.004  0.000 popen_spawn_win32.py:29(_close_handles)
       48  0.003  0.000  3.139  0.065 popen_spawn_win32.py:45(__init__)
      240  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
       48  0.000  0.000  0.001  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       48  0.001  0.000  3.144  0.066 process.py:110(start)
       16  0.000  0.000  0.004  0.000 process.py:128(terminate)
       16  0.000  0.000  0.173  0.011 process.py:142(join)
  2772852  4.711  0.000  15.540  0.000 process.py:153(is_alive)
       48  0.000  0.000  0.000  0.000 process.py:189(name)
       48  0.000  0.000  0.000  0.000 process.py:213(authkey)
       96  0.001  0.000  0.002  0.000 process.py:350(__reduce__)
       97  0.000  0.000  0.000  0.000 process.py:37(current_process)
       48  0.001  0.000  0.002  0.000 process.py:61(_cleanup)
       48  0.001  0.000  0.002  0.000 process.py:80(__init__)
       96  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
  2772932  0.682  0.000  0.682  0.000 process.py:99(_check_closed)
        1  0.000  0.000  0.000  0.000 random.py:480(choices)
        1  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
       48  0.000  0.000  0.000  0.000 reduction.py:223(_reduce_partial)
       96  0.001  0.000  0.001  0.000 reduction.py:38(__init__)
       96  0.001  0.000  0.012  0.000 reduction.py:58(dump)
       48  0.000  0.000  0.000  0.000 reduction.py:71(duplicate)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
   573013  0.133  0.000  0.133  0.000 shared_memory.py:204(buf)
       48  0.000  0.000  0.000  0.000 shared_memory.py:209(name)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
   191002  0.031  0.000  0.031  0.000 shared_memory.py:278(<lambda>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:280(<lambda>)
        3  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
   191003  0.608  0.000  1.037  0.000 shared_memory.py:371(_get_packing_format)
   191003  0.402  0.000  0.843  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
   191003  0.736  0.000  2.836  0.000 shared_memory.py:424(__getitem__)
       48  0.000  0.000  0.000  0.000 shared_memory.py:474(__reduce__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
   573012  0.195  0.000  0.195  0.000 shared_memory.py:505(_offset_data_start)
   382008  0.271  0.000  0.395  0.000 shared_memory.py:511(_offset_packing_formats)
   191004  0.147  0.000  0.339  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
       48  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       48  0.001  0.000  0.003  0.000 spawn.py:160(get_preparation_data)
       96  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       48  0.001  0.000  0.002  0.000 spawn.py:83(get_command_line)
      144  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       48  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       48  0.001  0.000  0.001  0.000 subprocess.py:300(_args_from_interpreter_flags)
       48  0.001  0.000  0.001  0.000 synchronize.py:100(__getstate__)
        1  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        1  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        1  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        1  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
       48  0.001  0.000  0.001  0.000 util.py:189(__init__)
       48  0.000  0.000  0.004  0.000 util.py:208(__call__)
       48  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
        1  0.000  0.000  0.000  0.000 util.py:48(debug)
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
   573009  0.216  0.000  0.216  0.000 {built-in method _struct.unpack_from}
      145  0.004  0.000  0.004  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
       48  0.002  0.000  0.002  0.000 {built-in method _winapi.CreatePipe}
       48  0.183  0.004  0.183  0.004 {built-in method _winapi.CreateProcess}
       48  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
       48  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       49  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
       16  0.004  0.000  0.004  0.000 {built-in method _winapi.TerminateProcess}
  2773179  2.229  0.000  2.229  0.000 {built-in method _winapi.WaitForSingleObject}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  24.826  24.826 {built-in method builtins.exec}
      769  0.001  0.000  0.001  0.000 {built-in method builtins.getattr}
      106  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
   191008  0.036  0.000  0.036  0.000 {built-in method builtins.len}
  2773163  0.976  0.000  0.976  0.000 {built-in method builtins.max}
       97  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
       48  0.001  0.000  0.001  0.000 {built-in method io.open}
        3  0.000  0.000  0.000  0.000 {built-in method math.ceil}
        8  0.000  0.000  0.000  0.000 {built-in method math.floor}
       48  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       48  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       96  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       48  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
  2773109  0.522  0.000  0.522  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
       48  2.933  0.061  2.933  0.061 {method '__exit__' of '_io._IOBase' objects}
       96  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       51  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
      144  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
   191005  0.059  0.000  0.059  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
      105  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       96  0.006  0.000  0.010  0.000 {method 'dump' of '_pickle.Pickler' objects}
        4  0.000  0.000  0.000  0.000 {method 'encode' of 'str' objects}
       48  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       96  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
      147  0.000  0.000  0.001  0.000 {method 'join' of 'str' objects}
        8  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
       48  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
      145  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
   191004  0.037  0.000  0.037  0.000 {method 'rstrip' of 'bytes' objects}
       96  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
      144  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
61250500 28.7346038 amongamongamong
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
         30864833 function calls in 28.729 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
      145  0.000  0.000  0.001  0.000 <frozen importlib._bootstrap>:405(parent)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       48  0.000  0.000  0.001  0.000 <frozen ntpath>:87(isabs)
        1  0.000  0.000  28.729  28.729 <string>:1(<module>)
        1  1.806  1.806  28.727  28.727 MultiProcessor2.py:36(multiProcessor2)
  3322970  1.886  0.000  20.672  0.000 MultiProcessor2.py:50(<lambda>)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        1  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
       48  0.000  0.000  2.516  0.052 context.py:222(_Popen)
       49  0.000  0.000  0.000  0.000 context.py:237(get_context)
       48  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       48  0.001  0.000  2.515  0.052 context.py:333(_Popen)
      240  0.000  0.000  0.000  0.000 context.py:365(get_spawning_popen)
       96  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
       48  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
        1  0.000  0.000  0.000  0.000 context.py:65(Lock)
  3323305  6.027  0.000  9.865  0.000 popen_spawn_win32.py:103(wait)
  3323289  1.889  0.000  11.567  0.000 popen_spawn_win32.py:121(poll)
       16  0.000  0.000  0.004  0.000 popen_spawn_win32.py:124(terminate)
       48  0.000  0.000  0.007  0.000 popen_spawn_win32.py:29(_close_handles)
       48  0.004  0.000  2.514  0.052 popen_spawn_win32.py:45(__init__)
      240  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
       48  0.000  0.000  0.001  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       48  0.001  0.000  2.519  0.052 process.py:110(start)
       16  0.000  0.000  0.004  0.000 process.py:128(terminate)
       16  0.000  0.000  0.187  0.012 process.py:142(join)
  3322970  5.737  0.000  18.785  0.000 process.py:153(is_alive)
       48  0.000  0.000  0.000  0.000 process.py:189(name)
       48  0.000  0.000  0.000  0.000 process.py:213(authkey)
       96  0.002  0.000  0.002  0.000 process.py:350(__reduce__)
       97  0.000  0.000  0.000  0.000 process.py:37(current_process)
       48  0.001  0.000  0.002  0.000 process.py:61(_cleanup)
       48  0.001  0.000  0.002  0.000 process.py:80(__init__)
       96  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
  3323050  0.822  0.000  0.822  0.000 process.py:99(_check_closed)
        1  0.000  0.000  0.000  0.000 random.py:480(choices)
        1  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
       48  0.000  0.000  0.000  0.000 reduction.py:223(_reduce_partial)
       96  0.002  0.000  0.002  0.000 reduction.py:38(__init__)
       96  0.001  0.000  0.015  0.000 reduction.py:58(dump)
       48  0.000  0.000  0.001  0.000 reduction.py:71(duplicate)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
   674749  0.152  0.000  0.152  0.000 shared_memory.py:204(buf)
       48  0.000  0.000  0.000  0.000 shared_memory.py:209(name)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
   224914  0.064  0.000  0.064  0.000 shared_memory.py:278(<lambda>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:280(<lambda>)
        3  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.001  0.001 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
   224915  0.755  0.000  1.291  0.000 shared_memory.py:371(_get_packing_format)
   224915  0.487  0.000  1.016  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
   224915  0.873  0.000  3.461  0.000 shared_memory.py:424(__getitem__)
       48  0.000  0.000  0.001  0.000 shared_memory.py:474(__reduce__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
   674748  0.245  0.000  0.245  0.000 shared_memory.py:505(_offset_data_start)
   449832  0.346  0.000  0.510  0.000 shared_memory.py:511(_offset_packing_formats)
   224916  0.176  0.000  0.414  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
       48  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       48  0.002  0.000  0.003  0.000 spawn.py:160(get_preparation_data)
       96  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       48  0.001  0.000  0.003  0.000 spawn.py:83(get_command_line)
      144  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       48  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       48  0.001  0.000  0.001  0.000 subprocess.py:300(_args_from_interpreter_flags)
       48  0.001  0.000  0.002  0.000 synchronize.py:100(__getstate__)
        1  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        1  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        1  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        1  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
       48  0.001  0.000  0.001  0.000 util.py:189(__init__)
       48  0.001  0.000  0.007  0.000 util.py:208(__call__)
       48  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
        1  0.000  0.000  0.000  0.000 util.py:48(debug)
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
   674745  0.249  0.000  0.249  0.000 {built-in method _struct.unpack_from}
      145  0.007  0.000  0.007  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
       48  0.002  0.000  0.002  0.000 {built-in method _winapi.CreatePipe}
       48  0.200  0.004  0.200  0.004 {built-in method _winapi.CreateProcess}
       48  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
       48  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       49  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
       16  0.004  0.000  0.004  0.000 {built-in method _winapi.TerminateProcess}
  3323296  2.686  0.000  2.686  0.000 {built-in method _winapi.WaitForSingleObject}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  28.729  28.729 {built-in method builtins.exec}
      769  0.001  0.000  0.001  0.000 {built-in method builtins.getattr}
      106  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
   224920  0.069  0.000  0.069  0.000 {built-in method builtins.len}
  3323280  1.151  0.000  1.151  0.000 {built-in method builtins.max}
       97  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
       48  0.001  0.000  0.001  0.000 {built-in method io.open}
        3  0.000  0.000  0.000  0.000 {built-in method math.ceil}
        8  0.000  0.000  0.000  0.000 {built-in method math.floor}
       48  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       48  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       96  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       48  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
  3323227  0.661  0.000  0.661  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
       48  2.283  0.048  2.283  0.048 {method '__exit__' of '_io._IOBase' objects}
       96  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       51  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
      144  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
   224917  0.071  0.000  0.071  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
      105  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       96  0.008  0.000  0.012  0.000 {method 'dump' of '_pickle.Pickler' objects}
        4  0.000  0.000  0.000  0.000 {method 'encode' of 'str' objects}
       48  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       96  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
      147  0.000  0.000  0.001  0.000 {method 'join' of 'str' objects}
        8  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
       48  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
      145  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
   224916  0.044  0.000  0.044  0.000 {method 'rstrip' of 'bytes' objects}
       96  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
      144  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
29250500 33.8736421 amongamongamong
Enter Password: q
Done
Since the goal was to remove filtering a bunch then the idea was to have the code wait until a signal that a process ended. Said signal came in the form of a multi processor event which was sent by a process on completion. In terms of performance it takes ~25 seconds for the hardest password in the 500 word dictionary of amongamongamong. However there were some issues, mainly in that the signal was sent slightly before the process properly finished causing me to have a timeout on the wait to prevent the program from halting. This meant that the filter was still running more then it has too as evident by the ~2500 calls to it rather then the theoretical 48.
def run(perms, arr, algorithm, password, words, lock, event):
    count = 0
    for p in perms:
        for w in words:
            count += 1
            word = "".join(list(p) + [w]).encode()
            hash = hashlib.new(algorithm)
            hash.update(word)
            if hash.digest() == password:
                with lock:
                    arr[2] = word
                    arr[0] = arr[0] + count
                    arr[1] = True
                event.set()
                return
    with lock:
        arr[0] = arr[0] + count
    event.set()
def multiProcessor2(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    arr = shared_memory.ShareableList([0, False, "\0" * 100])
    lock = multiprocessing.Lock()
    event = multiprocessing.Event()
    for i in range(1, wordLimit + 1):
        perms = itertools.product(words, repeat=i - 1)
        wordsLen = len(words)
        size = math.ceil(wordsLen / multiprocessing.cpu_count())
        processes = []
        for j in range(0, wordsLen, size):
            p = multiprocessing.Process(target=run,args=[perms, arr, algorithm, password, words[j : j + size], lock, event])
            p.start()
            processes.append(p)
        while len(processes) != 0:
            event.wait(timeout=0.1)
            event.clear()
            if arr[1]:
                break
            time.sleep(0.01)
            processes = list(filter(lambda p: p.is_alive(), processes))
        for p in processes:
            p.terminate()
            p.join()
        if arr[1]:
            break
    return arr[0], (time.time_ns() - start) / 1e9, arr[2].decode()Â
Longest Password is amongamongamong and will take around 125250500 iterations and around 33.817635 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
         35066 function calls in 19.610 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
      152  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:87(isabs)
        1  0.000  0.000  19.610  19.610 <string>:1(<module>)
        1  0.019  0.019  19.609  19.609 MultiProcessorEvent.py:38(multiProcessor2)
     2198  0.002  0.000  0.025  0.000 MultiProcessorEvent.py:58(<lambda>)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        6  0.000  0.000  0.000  0.000 context.py:187(get_context)
        6  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
       48  0.000  0.000  2.116  0.044 context.py:222(_Popen)
       50  0.000  0.000  0.000  0.000 context.py:237(get_context)
       48  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       48  0.001  0.000  2.116  0.044 context.py:333(_Popen)
     1008  0.000  0.000  0.001  0.000 context.py:365(get_spawning_popen)
       96  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
      336  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
        2  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 context.py:75(Condition)
        4  0.000  0.000  0.000  0.000 context.py:80(Semaphore)
        1  0.000  0.000  0.000  0.000 context.py:90(Event)
     2534  0.008  0.000  0.122  0.000 popen_spawn_win32.py:103(wait)
     2518  0.002  0.000  0.015  0.000 popen_spawn_win32.py:121(poll)
       16  0.000  0.000  0.003  0.000 popen_spawn_win32.py:124(terminate)
       48  0.000  0.000  0.003  0.000 popen_spawn_win32.py:29(_close_handles)
       48  0.002  0.000  2.115  0.044 popen_spawn_win32.py:45(__init__)
      240  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
      288  0.000  0.000  0.001  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       48  0.001  0.000  2.119  0.044 process.py:110(start)
       16  0.000  0.000  0.003  0.000 process.py:128(terminate)
       16  0.000  0.000  0.109  0.007 process.py:142(join)
     2198  0.007  0.000  0.023  0.000 process.py:153(is_alive)
       48  0.000  0.000  0.000  0.000 process.py:189(name)
       48  0.000  0.000  0.000  0.000 process.py:213(authkey)
       96  0.001  0.000  0.001  0.000 process.py:350(__reduce__)
      102  0.000  0.000  0.000  0.000 process.py:37(current_process)
       48  0.000  0.000  0.002  0.000 process.py:61(_cleanup)
       48  0.001  0.000  0.002  0.000 process.py:80(__init__)
       96  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
     2278  0.001  0.000  0.001  0.000 process.py:99(_check_closed)
        6  0.000  0.000  0.000  0.000 random.py:480(choices)
        6  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
       48  0.000  0.000  0.000  0.000 reduction.py:223(_reduce_partial)
       96  0.001  0.000  0.001  0.000 reduction.py:38(__init__)
       96  0.001  0.000  0.014  0.000 reduction.py:58(dump)
      288  0.000  0.000  0.001  0.000 reduction.py:71(duplicate)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
      451  0.000  0.000  0.000  0.000 shared_memory.py:204(buf)
       48  0.000  0.000  0.000  0.000 shared_memory.py:209(name)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
      148  0.000  0.000  0.000  0.000 shared_memory.py:278(<lambda>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:280(<lambda>)
        3  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
      149  0.001  0.000  0.003  0.000 shared_memory.py:371(_get_packing_format)
      149  0.001  0.000  0.002  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
      149  0.003  0.000  0.008  0.000 shared_memory.py:424(__getitem__)
       48  0.000  0.000  0.000  0.000 shared_memory.py:474(__reduce__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
      450  0.000  0.000  0.000  0.000 shared_memory.py:505(_offset_data_start)
      300  0.000  0.000  0.000  0.000 shared_memory.py:511(_offset_packing_formats)
      150  0.000  0.000  0.000  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
       48  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       48  0.001  0.000  0.002  0.000 spawn.py:160(get_preparation_data)
       96  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       48  0.000  0.000  0.002  0.000 spawn.py:83(get_command_line)
      144  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       48  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       48  0.001  0.000  0.001  0.000 subprocess.py:300(_args_from_interpreter_flags)
      288  0.001  0.000  0.003  0.000 synchronize.py:100(__getstate__)
        6  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        4  0.000  0.000  0.000  0.000 synchronize.py:132(__init__)
        2  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:219(__init__)
       48  0.000  0.000  0.000  0.000 synchronize.py:226(__getstate__)
      288  0.001  0.000  0.001  0.000 synchronize.py:236(__enter__)
      288  0.001  0.000  0.002  0.000 synchronize.py:239(__exit__)
        1  0.000  0.000  0.000  0.000 synchronize.py:242(_make_methods)
      134  0.004  0.000  14.683  0.110 synchronize.py:254(wait)
        1  0.000  0.000  0.000  0.000 synchronize.py:330(__init__)
      144  0.001  0.000  0.001  0.000 synchronize.py:347(clear)
      144  0.003  0.000  14.689  0.102 synchronize.py:351(wait)
        6  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        6  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
      288  0.001  0.000  0.001  0.000 synchronize.py:94(__enter__)
      288  0.000  0.000  0.001  0.000 synchronize.py:97(__exit__)
        6  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        6  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
       48  0.001  0.000  0.001  0.000 util.py:189(__init__)
       48  0.000  0.000  0.003  0.000 util.py:208(__call__)
       48  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
        6  0.000  0.000  0.000  0.000 util.py:48(debug)
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
      447  0.001  0.000  0.001  0.000 {built-in method _struct.unpack_from}
      145  0.003  0.000  0.003  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
       48  0.001  0.000  0.001  0.000 {built-in method _winapi.CreatePipe}
       48  0.158  0.003  0.158  0.003 {built-in method _winapi.CreateProcess}
      288  0.001  0.000  0.001  0.000 {built-in method _winapi.DuplicateHandle}
      288  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       49  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
       16  0.003  0.000  0.003  0.000 {built-in method _winapi.TerminateProcess}
     2524  0.112  0.000  0.112  0.000 {built-in method _winapi.WaitForSingleObject}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  19.610  19.610 {built-in method builtins.exec}
     1542  0.001  0.000  0.001  0.000 {built-in method builtins.getattr}
      106  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
      162  0.000  0.000  0.000  0.000 {built-in method builtins.len}
     2508  0.002  0.000  0.002  0.000 {built-in method builtins.max}
      102  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
       48  0.001  0.000  0.001  0.000 {built-in method io.open}
        3  0.000  0.000  0.000  0.000 {built-in method math.ceil}
       48  0.000  0.000  0.000  0.000 {built-in method math.floor}
       48  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       48  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       96  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       48  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
     2460  0.001  0.000  0.001  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
      143  2.631  0.018  2.631  0.018 {built-in method time.sleep}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
      288  0.000  0.000  0.000  0.000 {method '__enter__' of '_multiprocessing.SemLock' objects}
       48  1.933  0.040  1.933  0.040 {method '__exit__' of '_io._IOBase' objects}
      288  0.001  0.000  0.001  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
      134  0.000  0.000  0.000  0.000 {method '_count' of '_multiprocessing.SemLock' objects}
      134  0.000  0.000  0.000  0.000 {method '_is_mine' of '_multiprocessing.SemLock' objects}
      700  14.679  0.021  14.679  0.021 {method 'acquire' of '_multiprocessing.SemLock' objects}
       96  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       51  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
      144  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
      151  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
      106  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       96  0.007  0.000  0.012  0.000 {method 'dump' of '_pickle.Pickler' objects}
        4  0.000  0.000  0.000  0.000 {method 'encode' of 'str' objects}
       48  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       96  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
      152  0.000  0.000  0.001  0.000 {method 'join' of 'str' objects}
       48  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
      433  0.001  0.000  0.001  0.000 {method 'release' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
       48  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
      152  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
      150  0.000  0.000  0.000  0.000 {method 'rstrip' of 'bytes' objects}
       96  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
      144  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
5250500 23.4468787 amongamongamong
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
         40604 function calls in 24.135 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
      152  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       48  0.000  0.000  0.001  0.000 <frozen ntpath>:87(isabs)
        1  0.000  0.000  24.135  24.135 <string>:1(<module>)
        1  0.021  0.021  24.133  24.133 MultiProcessorEvent.py:38(multiProcessor2)
     2707  0.003  0.000  0.032  0.000 MultiProcessorEvent.py:58(<lambda>)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        6  0.000  0.000  0.000  0.000 context.py:187(get_context)
        6  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
       48  0.000  0.000  2.376  0.050 context.py:222(_Popen)
       50  0.000  0.000  0.000  0.000 context.py:237(get_context)
       48  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       48  0.001  0.000  2.376  0.049 context.py:333(_Popen)
     1008  0.000  0.000  0.001  0.000 context.py:365(get_spawning_popen)
       96  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
      336  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
        2  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 context.py:75(Condition)
        4  0.000  0.000  0.000  0.000 context.py:80(Semaphore)
        1  0.000  0.000  0.000  0.000 context.py:90(Event)
     3046  0.010  0.000  0.219  0.000 popen_spawn_win32.py:103(wait)
     3030  0.002  0.000  0.018  0.000 popen_spawn_win32.py:121(poll)
       16  0.000  0.000  0.004  0.000 popen_spawn_win32.py:124(terminate)
       48  0.000  0.000  0.004  0.000 popen_spawn_win32.py:29(_close_handles)
       48  0.003  0.000  2.375  0.049 popen_spawn_win32.py:45(__init__)
      240  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
      288  0.000  0.000  0.001  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       48  0.001  0.000  2.379  0.050 process.py:110(start)
       16  0.000  0.000  0.004  0.000 process.py:128(terminate)
       16  0.000  0.000  0.204  0.013 process.py:142(join)
     2707  0.010  0.000  0.029  0.000 process.py:153(is_alive)
       48  0.000  0.000  0.000  0.000 process.py:189(name)
       48  0.000  0.000  0.000  0.000 process.py:213(authkey)
       96  0.001  0.000  0.002  0.000 process.py:350(__reduce__)
      102  0.000  0.000  0.000  0.000 process.py:37(current_process)
       48  0.001  0.000  0.002  0.000 process.py:61(_cleanup)
       48  0.001  0.000  0.002  0.000 process.py:80(__init__)
       96  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
     2787  0.002  0.000  0.002  0.000 process.py:99(_check_closed)
        6  0.000  0.000  0.000  0.000 random.py:480(choices)
        6  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
       48  0.000  0.000  0.000  0.000 reduction.py:223(_reduce_partial)
       96  0.001  0.000  0.001  0.000 reduction.py:38(__init__)
       96  0.001  0.000  0.015  0.000 reduction.py:58(dump)
      288  0.000  0.000  0.001  0.000 reduction.py:71(duplicate)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
      547  0.000  0.000  0.000  0.000 shared_memory.py:204(buf)
       48  0.000  0.000  0.000  0.000 shared_memory.py:209(name)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
      180  0.000  0.000  0.000  0.000 shared_memory.py:278(<lambda>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:280(<lambda>)
        3  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
      181  0.002  0.000  0.004  0.000 shared_memory.py:371(_get_packing_format)
      181  0.001  0.000  0.002  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
      181  0.003  0.000  0.009  0.000 shared_memory.py:424(__getitem__)
       48  0.000  0.000  0.000  0.000 shared_memory.py:474(__reduce__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
      546  0.001  0.000  0.001  0.000 shared_memory.py:505(_offset_data_start)
      364  0.000  0.000  0.001  0.000 shared_memory.py:511(_offset_packing_formats)
      182  0.000  0.000  0.001  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
       48  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       48  0.001  0.000  0.003  0.000 spawn.py:160(get_preparation_data)
       96  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       48  0.001  0.000  0.002  0.000 spawn.py:83(get_command_line)
      144  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       48  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       48  0.001  0.000  0.001  0.000 subprocess.py:300(_args_from_interpreter_flags)
      288  0.001  0.000  0.003  0.000 synchronize.py:100(__getstate__)
        6  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        4  0.000  0.000  0.000  0.000 synchronize.py:132(__init__)
        2  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:219(__init__)
       48  0.000  0.000  0.000  0.000 synchronize.py:226(__getstate__)
      352  0.001  0.000  0.002  0.000 synchronize.py:236(__enter__)
      352  0.001  0.000  0.002  0.000 synchronize.py:239(__exit__)
        1  0.000  0.000  0.000  0.000 synchronize.py:242(_make_methods)
      168  0.005  0.000  18.400  0.110 synchronize.py:254(wait)
        1  0.000  0.000  0.000  0.000 synchronize.py:330(__init__)
      176  0.001  0.000  0.002  0.000 synchronize.py:347(clear)
      176  0.004  0.000  18.408  0.105 synchronize.py:351(wait)
        6  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        6  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
      352  0.001  0.000  0.001  0.000 synchronize.py:94(__enter__)
      352  0.001  0.000  0.001  0.000 synchronize.py:97(__exit__)
        6  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        6  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
       48  0.001  0.000  0.001  0.000 util.py:189(__init__)
       48  0.000  0.000  0.004  0.000 util.py:208(__call__)
       48  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
        6  0.000  0.000  0.000  0.000 util.py:48(debug)
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
      543  0.001  0.000  0.001  0.000 {built-in method _struct.unpack_from}
      145  0.004  0.000  0.004  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
       48  0.002  0.000  0.002  0.000 {built-in method _winapi.CreatePipe}
       48  0.148  0.003  0.148  0.003 {built-in method _winapi.CreateProcess}
      288  0.000  0.000  0.000  0.000 {built-in method _winapi.DuplicateHandle}
      288  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       49  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
       16  0.004  0.000  0.004  0.000 {built-in method _winapi.TerminateProcess}
     3037  0.207  0.000  0.207  0.000 {built-in method _winapi.WaitForSingleObject}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  24.135  24.135 {built-in method builtins.exec}
     1542  0.001  0.000  0.001  0.000 {built-in method builtins.getattr}
      106  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
      194  0.000  0.000  0.000  0.000 {built-in method builtins.len}
     3021  0.002  0.000  0.002  0.000 {built-in method builtins.max}
      102  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
       48  0.001  0.000  0.001  0.000 {built-in method io.open}
        3  0.000  0.000  0.000  0.000 {built-in method math.ceil}
       48  0.000  0.000  0.000  0.000 {built-in method math.floor}
       48  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       48  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       96  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       48  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
     2969  0.001  0.000  0.001  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
      175  3.068  0.018  3.068  0.018 {built-in method time.sleep}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
      352  0.000  0.000  0.000  0.000 {method '__enter__' of '_multiprocessing.SemLock' objects}
       48  2.199  0.046  2.199  0.046 {method '__exit__' of '_io._IOBase' objects}
      352  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
      168  0.000  0.000  0.000  0.000 {method '_count' of '_multiprocessing.SemLock' objects}
      168  0.000  0.000  0.000  0.000 {method '_is_mine' of '_multiprocessing.SemLock' objects}
      864  18.395  0.021  18.395  0.021 {method 'acquire' of '_multiprocessing.SemLock' objects}
       96  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       51  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
      144  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
      183  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
      105  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       96  0.008  0.000  0.013  0.000 {method 'dump' of '_pickle.Pickler' objects}
        4  0.000  0.000  0.000  0.000 {method 'encode' of 'str' objects}
       48  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       96  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
      152  0.000  0.000  0.001  0.000 {method 'join' of 'str' objects}
       48  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
      532  0.001  0.000  0.001  0.000 {method 'release' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
       48  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
      152  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
      182  0.000  0.000  0.000  0.000 {method 'rstrip' of 'bytes' objects}
       96  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
      144  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
5250500 26.1561529 amongamongamong
Enter Password: q
Done
To solve the previous issues I switched from events to pipes which unlike the events, at least to my knowledge, have a buffer so they can store how much data was sent. This solved the issue of what if 2 processors send a event before the event was cleared. I also realized that due to terminating processes my count was wrong in that it wasn't a accurate representation of how many comparisons I did. This is due to me only adding my count at the end of the process. Which of course only happens when the process finishes, which terminate doesn't do. Thus I resolved this issue by using events and threads to signal when a process should end and then only join them rather then terminate them, this also removed the need to filter processes which further improved performance. Â In terms of performance it takes ~22 seconds for the hardest password in the 500 word dictionary of amongamongamong. Through the cProfiler we see that the most time is spent on waiting indicating that we should now look at the processor code to see if it can be optimized.
class CancellationToken:
   def __init__(self):
       self.is_cancelled = False
   def cancel(self):
       self.is_cancelled = True
def wait(event, token):
    event.wait()
    token.cancel()
def run(perms, arr, algorithm, password, words, lock, conn, event):
    count = 0
    token = CancellationToken()
    thread = threading.Thread(target=wait, args=[event, token])
    thread.start()
    for p in perms:
        for w in words:
            count += 1
            word = "".join(list(p) + [w]).encode()
            hash = hashlib.new(algorithm)
            hash.update(word)
            if hash.digest() == password:
                event.set()
                with lock:
                    arr[2] = word
                    arr[1] = True
            elif token.is_cancelled: break
        if token.is_cancelled: break
    with lock:
        arr[0] = arr[0] + count
        conn.send_bytes(b'\x00')
    thread.join()
def multiProcessor2(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    arr = shared_memory.ShareableList([0, False, "\0" * 100])
    lock = multiprocessing.Lock()
    recv, send = multiprocessing.Pipe()
    event = multiprocessing.Event()
    for i in range(1, wordLimit + 1):
        perms = itertools.product(words, repeat=i - 1)
        wordsLen = len(words)
        size = math.ceil(wordsLen / multiprocessing.cpu_count())
        processes = []
        for j in range(0, wordsLen, size):
            p = multiprocessing.Process(target=run,args=[perms, arr, algorithm, password, words[j : j + size], lock, send, event])
            p.start()
            processes.append(p)
        completed = 0
        while completed != len(processes):
            recv.recv_bytes()
            if arr[1]:
                break
            completed += 1
        event.set()
        for p in processes:
            p.join()
        event.clear()
        if arr[1]:
            break
    recv.close()
    send.close()
    return arr[0], (time.time_ns() - start) / 1e9, arr[2].decode()Â
Longest Password is amongamongamong and will take around 86188000 iterations and around 21.55 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
         13117 function calls in 20.362 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
      153  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        1  0.000  0.000  0.000  0.000 <frozen ntpath>:107(join)
        2  0.000  0.000  0.000  0.000 <frozen ntpath>:154(splitdrive)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:87(isabs)
        1  0.000  0.000  20.362  20.362 <string>:1(<module>)
        1  0.001  0.001  20.361  20.361 MultiProcessorPipe.py:51(multiProcessor2)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        2  0.000  0.000  0.000  0.000 connection.py:118(__init__)
        2  0.000  0.000  0.000  0.000 connection.py:131(__del__)
       81  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
       33  0.000  0.000  0.000  0.000 connection.py:139(_check_readable)
       96  0.000  0.000  0.000  0.000 connection.py:159(readable)
       96  0.000  0.000  0.000  0.000 connection.py:164(writable)
       48  0.000  0.000  0.000  0.000 connection.py:169(fileno)
        2  0.000  0.000  0.000  0.000 connection.py:174(close)
       33  0.000  0.000  17.481  0.530 connection.py:208(recv_bytes)
        2  0.000  0.000  0.000  0.000 connection.py:277(_close)
       33  0.001  0.000  17.481  0.530 connection.py:310(_recv_bytes)
        1  0.000  0.000  0.000  0.000 connection.py:552(Pipe)
        1  0.000  0.000  0.000  0.000 connection.py:70(arbitrary_address)
       48  0.000  0.000  0.001  0.000 connection.py:973(reduce_pipe_connection)
        6  0.000  0.000  0.000  0.000 context.py:187(get_context)
        6  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
       48  0.000  0.000  2.009  0.042 context.py:222(_Popen)
       50  0.000  0.000  0.000  0.000 context.py:237(get_context)
       48  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       48  0.001  0.000  2.009  0.042 context.py:333(_Popen)
     1008  0.000  0.000  0.000  0.000 context.py:365(get_spawning_popen)
       96  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
      336  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
        1  0.000  0.000  0.000  0.000 context.py:60(Pipe)
        2  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 context.py:75(Condition)
        4  0.000  0.000  0.000  0.000 context.py:80(Semaphore)
        1  0.000  0.000  0.000  0.000 context.py:90(Event)
      408  0.001  0.000  0.629  0.002 popen_spawn_win32.py:103(wait)
      360  0.000  0.000  0.001  0.000 popen_spawn_win32.py:121(poll)
       48  0.000  0.000  0.002  0.000 popen_spawn_win32.py:29(_close_handles)
       48  0.002  0.000  2.008  0.042 popen_spawn_win32.py:45(__init__)
      240  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
      288  0.000  0.000  0.001  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       48  0.001  0.000  2.012  0.042 process.py:110(start)
       48  0.000  0.000  0.628  0.013 process.py:142(join)
       48  0.000  0.000  0.000  0.000 process.py:189(name)
       48  0.000  0.000  0.000  0.000 process.py:213(authkey)
       96  0.001  0.000  0.001  0.000 process.py:350(__reduce__)
      102  0.000  0.000  0.000  0.000 process.py:37(current_process)
       48  0.000  0.000  0.002  0.000 process.py:61(_cleanup)
       48  0.001  0.000  0.001  0.000 process.py:80(__init__)
       96  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
       96  0.000  0.000  0.000  0.000 process.py:99(_check_closed)
        7  0.000  0.000  0.000  0.000 random.py:480(choices)
        7  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
       48  0.000  0.000  0.001  0.000 reduction.py:106(__init__)
       48  0.000  0.000  0.000  0.000 reduction.py:223(_reduce_partial)
       96  0.001  0.000  0.001  0.000 reduction.py:38(__init__)
       96  0.001  0.000  0.014  0.000 reduction.py:58(dump)
      288  0.000  0.000  0.001  0.000 reduction.py:71(duplicate)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
      118  0.000  0.000  0.000  0.000 shared_memory.py:204(buf)
       48  0.000  0.000  0.000  0.000 shared_memory.py:209(name)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
       37  0.000  0.000  0.000  0.000 shared_memory.py:278(<lambda>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:280(<lambda>)
        3  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
       38  0.000  0.000  0.000  0.000 shared_memory.py:371(_get_packing_format)
       38  0.000  0.000  0.000  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
       38  0.000  0.000  0.001  0.000 shared_memory.py:424(__getitem__)
       48  0.000  0.000  0.000  0.000 shared_memory.py:474(__reduce__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
      117  0.000  0.000  0.000  0.000 shared_memory.py:505(_offset_data_start)
       78  0.000  0.000  0.000  0.000 shared_memory.py:511(_offset_packing_formats)
       39  0.000  0.000  0.000  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
       48  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       48  0.001  0.000  0.002  0.000 spawn.py:160(get_preparation_data)
       96  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       48  0.000  0.000  0.002  0.000 spawn.py:83(get_command_line)
      144  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       48  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       48  0.001  0.000  0.001  0.000 subprocess.py:300(_args_from_interpreter_flags)
      288  0.001  0.000  0.002  0.000 synchronize.py:100(__getstate__)
        6  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        4  0.000  0.000  0.000  0.000 synchronize.py:132(__init__)
        2  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:219(__init__)
       48  0.000  0.000  0.000  0.000 synchronize.py:226(__getstate__)
        6  0.000  0.000  0.234  0.039 synchronize.py:236(__enter__)
        6  0.000  0.000  0.000  0.000 synchronize.py:239(__exit__)
        1  0.000  0.000  0.000  0.000 synchronize.py:242(_make_methods)
        3  0.000  0.000  0.000  0.000 synchronize.py:277(notify)
        3  0.000  0.000  0.000  0.000 synchronize.py:303(notify_all)
        1  0.000  0.000  0.000  0.000 synchronize.py:330(__init__)
        3  0.000  0.000  0.235  0.078 synchronize.py:341(set)
        3  0.000  0.000  0.000  0.000 synchronize.py:347(clear)
        6  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        6  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        6  0.000  0.000  0.234  0.039 synchronize.py:94(__enter__)
        6  0.000  0.000  0.000  0.000 synchronize.py:97(__exit__)
        7  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        7  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        1  0.000  0.000  0.000  0.000 tempfile.py:230(_get_candidate_names)
        1  0.000  0.000  0.000  0.000 tempfile.py:401(mktemp)
        1  0.000  0.000  0.000  0.000 tempfile.py:77(_exists)
       48  0.001  0.000  0.001  0.000 util.py:189(__init__)
       48  0.000  0.000  0.002  0.000 util.py:208(__call__)
       48  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
        6  0.000  0.000  0.000  0.000 util.py:48(debug)
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
      114  0.000  0.000  0.000  0.000 {built-in method _struct.unpack_from}
      195  0.002  0.000  0.002  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.ConnectNamedPipe}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFile}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateNamedPipe}
       48  0.001  0.000  0.001  0.000 {built-in method _winapi.CreatePipe}
       48  0.176  0.004  0.176  0.004 {built-in method _winapi.CreateProcess}
      336  0.001  0.000  0.001  0.000 {built-in method _winapi.DuplicateHandle}
      336  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       48  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
       48  0.000  0.000  0.000  0.000 {built-in method _winapi.OpenProcess}
       33  0.000  0.000  0.000  0.000 {built-in method _winapi.ReadFile}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.SetNamedPipeHandleState}
       20  17.480  0.874  17.480  0.874 {built-in method _winapi.WaitForMultipleObjects}
      408  0.628  0.002  0.628  0.002 {built-in method _winapi.WaitForSingleObject}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  20.362  20.362 {built-in method builtins.exec}
     1543  0.001  0.000  0.001  0.000 {built-in method builtins.getattr}
      108  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
       54  0.000  0.000  0.000  0.000 {built-in method builtins.len}
      360  0.000  0.000  0.000  0.000 {built-in method builtins.max}
      104  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
       48  0.001  0.000  0.001  0.000 {built-in method io.open}
        3  0.000  0.000  0.000  0.000 {built-in method math.ceil}
       56  0.000  0.000  0.000  0.000 {built-in method math.floor}
       48  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       48  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       99  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       48  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
      344  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.lstat}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
       34  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
        6  0.234  0.039  0.234  0.039 {method '__enter__' of '_multiprocessing.SemLock' objects}
       48  1.809  0.038  1.809  0.038 {method '__exit__' of '_io._IOBase' objects}
        6  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
        3  0.000  0.000  0.000  0.000 {method '_is_mine' of '_multiprocessing.SemLock' objects}
       81  0.000  0.000  0.000  0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
       96  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       51  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
      144  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
       40  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
       96  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       96  0.006  0.000  0.012  0.000 {method 'dump' of '_pickle.Pickler' objects}
        4  0.000  0.000  0.000  0.000 {method 'encode' of 'str' objects}
        2  0.000  0.000  0.000  0.000 {method 'find' of 'str' objects}
       48  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
       33  0.000  0.000  0.000  0.000 {method 'getbuffer' of '_winapi.Overlapped' objects}
       33  0.000  0.000  0.000  0.000 {method 'getvalue' of '_io.BytesIO' objects}
       48  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       96  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
      153  0.000  0.000  0.001  0.000 {method 'join' of 'str' objects}
       56  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
       35  0.000  0.000  0.000  0.000 {method 'release' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
       49  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
      153  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
       39  0.000  0.000  0.000  0.000 {method 'rstrip' of 'bytes' objects}
       96  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
      144  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
        1  0.000  0.000  0.000  0.000 {method 'upper' of 'str' objects}
       33  0.000  0.000  0.000  0.000 {method 'write' of '_io.BytesIO' objects}
86464053 20.2589443 amongamongamong
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
         13118 function calls in 22.426 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
      153  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        1  0.000  0.000  0.000  0.000 <frozen ntpath>:107(join)
        2  0.000  0.000  0.000  0.000 <frozen ntpath>:154(splitdrive)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:538(normpath)
       48  0.000  0.000  0.000  0.000 <frozen ntpath>:87(isabs)
        1  0.000  0.000  22.426  22.426 <string>:1(<module>)
        1  0.001  0.001  22.424  22.424 MultiProcessorPipe.py:51(multiProcessor2)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:39(_remove)
       48  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        2  0.000  0.000  0.000  0.000 connection.py:118(__init__)
        2  0.000  0.000  0.000  0.000 connection.py:131(__del__)
       81  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
       33  0.000  0.000  0.000  0.000 connection.py:139(_check_readable)
       96  0.000  0.000  0.000  0.000 connection.py:159(readable)
       96  0.000  0.000  0.000  0.000 connection.py:164(writable)
       48  0.000  0.000  0.000  0.000 connection.py:169(fileno)
        2  0.000  0.000  0.000  0.000 connection.py:174(close)
       33  0.000  0.000  19.322  0.586 connection.py:208(recv_bytes)
        2  0.000  0.000  0.000  0.000 connection.py:277(_close)
       33  0.001  0.000  19.322  0.586 connection.py:310(_recv_bytes)
        1  0.000  0.000  0.000  0.000 connection.py:552(Pipe)
        1  0.000  0.000  0.000  0.000 connection.py:70(arbitrary_address)
       48  0.001  0.000  0.001  0.000 connection.py:973(reduce_pipe_connection)
        6  0.000  0.000  0.000  0.000 context.py:187(get_context)
        6  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
       48  0.000  0.000  2.174  0.045 context.py:222(_Popen)
       50  0.000  0.000  0.000  0.000 context.py:237(get_context)
       48  0.000  0.000  0.000  0.000 context.py:253(get_start_method)
       48  0.001  0.000  2.174  0.045 context.py:333(_Popen)
     1008  0.000  0.000  0.001  0.000 context.py:365(get_spawning_popen)
       96  0.000  0.000  0.000  0.000 context.py:368(set_spawning_popen)
      336  0.000  0.000  0.000  0.000 context.py:371(assert_spawning)
        3  0.000  0.000  0.000  0.000 context.py:41(cpu_count)
        1  0.000  0.000  0.000  0.000 context.py:60(Pipe)
        2  0.000  0.000  0.000  0.000 context.py:65(Lock)
        1  0.000  0.000  0.000  0.000 context.py:75(Condition)
        4  0.000  0.000  0.000  0.000 context.py:80(Semaphore)
        1  0.000  0.000  0.000  0.000 context.py:90(Event)
      408  0.001  0.000  0.668  0.002 popen_spawn_win32.py:103(wait)
      360  0.000  0.000  0.001  0.000 popen_spawn_win32.py:121(poll)
       48  0.000  0.000  0.002  0.000 popen_spawn_win32.py:29(_close_handles)
       48  0.002  0.000  2.173  0.045 popen_spawn_win32.py:45(__init__)
      240  0.000  0.000  0.000  0.000 popen_spawn_win32.py:70(<genexpr>)
      288  0.000  0.000  0.001  0.000 popen_spawn_win32.py:99(duplicate_for_child)
       48  0.001  0.000  2.177  0.045 process.py:110(start)
       48  0.000  0.000  0.667  0.014 process.py:142(join)
       48  0.000  0.000  0.000  0.000 process.py:189(name)
       48  0.000  0.000  0.000  0.000 process.py:213(authkey)
       96  0.001  0.000  0.001  0.000 process.py:350(__reduce__)
      102  0.000  0.000  0.000  0.000 process.py:37(current_process)
       48  0.001  0.000  0.002  0.000 process.py:61(_cleanup)
       48  0.001  0.000  0.002  0.000 process.py:80(__init__)
       96  0.000  0.000  0.000  0.000 process.py:94(<genexpr>)
       96  0.000  0.000  0.000  0.000 process.py:99(_check_closed)
        7  0.000  0.000  0.000  0.000 random.py:480(choices)
        7  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
       48  0.000  0.000  0.001  0.000 reduction.py:106(__init__)
       48  0.000  0.000  0.000  0.000 reduction.py:223(_reduce_partial)
       96  0.001  0.000  0.001  0.000 reduction.py:38(__init__)
       96  0.001  0.000  0.015  0.000 reduction.py:58(dump)
      288  0.000  0.000  0.001  0.000 reduction.py:71(duplicate)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
      118  0.000  0.000  0.000  0.000 shared_memory.py:204(buf)
       48  0.000  0.000  0.000  0.000 shared_memory.py:209(name)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
       37  0.000  0.000  0.000  0.000 shared_memory.py:278(<lambda>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:280(<lambda>)
        3  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
       38  0.000  0.000  0.000  0.000 shared_memory.py:371(_get_packing_format)
       38  0.000  0.000  0.000  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
       38  0.000  0.000  0.001  0.000 shared_memory.py:424(__getitem__)
       48  0.000  0.000  0.000  0.000 shared_memory.py:474(__reduce__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
      117  0.000  0.000  0.000  0.000 shared_memory.py:505(_offset_data_start)
       78  0.000  0.000  0.000  0.000 shared_memory.py:511(_offset_packing_formats)
       39  0.000  0.000  0.000  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
       48  0.000  0.000  0.000  0.000 spawn.py:138(_check_not_importing_main)
       48  0.001  0.000  0.002  0.000 spawn.py:160(get_preparation_data)
       96  0.000  0.000  0.000  0.000 spawn.py:45(get_executable)
       48  0.001  0.000  0.002  0.000 spawn.py:83(get_command_line)
      144  0.000  0.000  0.000  0.000 spawn.py:92(<genexpr>)
       48  0.000  0.000  0.000  0.000 subprocess.py:290(_optim_args_from_interpreter_flags)
       48  0.001  0.000  0.001  0.000 subprocess.py:300(_args_from_interpreter_flags)
      288  0.001  0.000  0.003  0.000 synchronize.py:100(__getstate__)
        6  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        4  0.000  0.000  0.000  0.000 synchronize.py:132(__init__)
        2  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:219(__init__)
       48  0.000  0.000  0.000  0.000 synchronize.py:226(__getstate__)
        6  0.000  0.000  0.251  0.042 synchronize.py:236(__enter__)
        6  0.000  0.000  0.000  0.000 synchronize.py:239(__exit__)
        1  0.000  0.000  0.000  0.000 synchronize.py:242(_make_methods)
        3  0.000  0.000  0.000  0.000 synchronize.py:277(notify)
        3  0.000  0.000  0.000  0.000 synchronize.py:303(notify_all)
        1  0.000  0.000  0.000  0.000 synchronize.py:330(__init__)
        3  0.000  0.000  0.252  0.084 synchronize.py:341(set)
        3  0.000  0.000  0.000  0.000 synchronize.py:347(clear)
        6  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        6  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        6  0.000  0.000  0.251  0.042 synchronize.py:94(__enter__)
        6  0.000  0.000  0.000  0.000 synchronize.py:97(__exit__)
        7  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        7  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        1  0.000  0.000  0.000  0.000 tempfile.py:230(_get_candidate_names)
        1  0.000  0.000  0.000  0.000 tempfile.py:401(mktemp)
        1  0.000  0.000  0.000  0.000 tempfile.py:77(_exists)
       48  0.001  0.000  0.001  0.000 util.py:189(__init__)
       48  0.000  0.000  0.002  0.000 util.py:208(__call__)
       48  0.000  0.000  0.000  0.000 util.py:44(sub_debug)
        6  0.000  0.000  0.000  0.000 util.py:48(debug)
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
      114  0.000  0.000  0.000  0.000 {built-in method _struct.unpack_from}
      195  0.002  0.000  0.002  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.ConnectNamedPipe}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFile}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateNamedPipe}
       48  0.001  0.000  0.001  0.000 {built-in method _winapi.CreatePipe}
       48  0.162  0.003  0.162  0.003 {built-in method _winapi.CreateProcess}
      336  0.001  0.000  0.001  0.000 {built-in method _winapi.DuplicateHandle}
      336  0.000  0.000  0.000  0.000 {built-in method _winapi.GetCurrentProcess}
       48  0.000  0.000  0.000  0.000 {built-in method _winapi.GetExitCodeProcess}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
       48  0.000  0.000  0.000  0.000 {built-in method _winapi.OpenProcess}
       33  0.000  0.000  0.000  0.000 {built-in method _winapi.ReadFile}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.SetNamedPipeHandleState}
       21  19.321  0.920  19.321  0.920 {built-in method _winapi.WaitForMultipleObjects}
      408  0.667  0.002  0.667  0.002 {built-in method _winapi.WaitForSingleObject}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  22.426  22.426 {built-in method builtins.exec}
     1543  0.001  0.000  0.001  0.000 {built-in method builtins.getattr}
      108  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
       54  0.000  0.000  0.000  0.000 {built-in method builtins.len}
      360  0.000  0.000  0.000  0.000 {built-in method builtins.max}
      104  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
       48  0.001  0.000  0.001  0.000 {built-in method io.open}
        3  0.000  0.000  0.000  0.000 {built-in method math.ceil}
       56  0.000  0.000  0.000  0.000 {built-in method math.floor}
       48  0.000  0.000  0.000  0.000 {built-in method msvcrt.open_osfhandle}
       48  0.000  0.000  0.000  0.000 {built-in method nt._path_normpath}
        3  0.000  0.000  0.000  0.000 {built-in method nt.cpu_count}
       99  0.000  0.000  0.000  0.000 {built-in method nt.fspath}
       48  0.000  0.000  0.000  0.000 {built-in method nt.getcwd}
      344  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.lstat}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
        2  0.000  0.000  0.000  0.000 {built-in method time.time_ns}
       34  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
        6  0.251  0.042  0.251  0.042 {method '__enter__' of '_multiprocessing.SemLock' objects}
       48  1.985  0.041  1.985  0.041 {method '__exit__' of '_io._IOBase' objects}
        6  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
        3  0.000  0.000  0.000  0.000 {method '_is_mine' of '_multiprocessing.SemLock' objects}
       81  0.000  0.000  0.000  0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
       96  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
       51  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
      144  0.000  0.000  0.000  0.000 {method 'copy' of 'dict' objects}
       48  0.000  0.000  0.000  0.000 {method 'copy' of 'list' objects}
       40  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
        1  0.000  0.000  0.000  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
       96  0.000  0.000  0.000  0.000 {method 'discard' of 'set' objects}
       96  0.007  0.000  0.013  0.000 {method 'dump' of '_pickle.Pickler' objects}
        4  0.000  0.000  0.000  0.000 {method 'encode' of 'str' objects}
        2  0.000  0.000  0.000  0.000 {method 'find' of 'str' objects}
       48  0.000  0.000  0.000  0.000 {method 'get' of 'dict' objects}
       33  0.000  0.000  0.000  0.000 {method 'getbuffer' of '_winapi.Overlapped' objects}
       33  0.000  0.000  0.000  0.000 {method 'getvalue' of '_io.BytesIO' objects}
       48  0.000  0.000  0.000  0.000 {method 'index' of 'list' objects}
       96  0.000  0.000  0.000  0.000 {method 'items' of 'dict' objects}
      153  0.000  0.000  0.001  0.000 {method 'join' of 'str' objects}
       56  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
       35  0.000  0.000  0.000  0.000 {method 'release' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
       49  0.000  0.000  0.000  0.000 {method 'replace' of 'str' objects}
      153  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
       39  0.000  0.000  0.000  0.000 {method 'rstrip' of 'bytes' objects}
       96  0.000  0.000  0.000  0.000 {method 'startswith' of 'str' objects}
      144  0.000  0.000  0.000  0.000 {method 'update' of 'dict' objects}
        1  0.000  0.000  0.000  0.000 {method 'upper' of 'str' objects}
       33  0.000  0.000  0.000  0.000 {method 'write' of '_io.BytesIO' objects}
88033400 24.2802704 amongamongamong
Enter Password: q
Done
The first step in optimizing the processor code was to run a cProfile on the code, that then highlighted many bottlenecks that I could solve. The main bottlenecks unsurprisingly involved hashing, in that new, update and digest where the main times but also encoding and join. For the hashing bottleneck I brought new out of the inner loop and instead used update and copy to update a hash object instead of creating a new one. For the encoding I opted to encode words in main as that let me encode all permutations before hand. For join there was nothing specific but it did decrease most likely due to using bytes instead of strings. In terms of performance there was a drastic decrease with it taking ~14 seconds for the hardest password in the 500 word dictionary of amongamongamong. Without some major changes I doubt the processing code will be any faster.
Longest Password is amongamongamong and will take around 86188000 iterations and around 21.55 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
85592459 20.6133822 amongamongamong
         48000204 function calls in 20.794 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
        1  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        1  0.000  0.000  20.794  20.794 <string>:1(<module>)
        1  0.000  0.000  0.000  0.000 MultiProcessorPipe2.py:17(__init__)
        1  10.553  10.553  20.793  20.793 MultiProcessorPipe2.py:51(run)
        1  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        1  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
        1  0.000  0.000  0.000  0.000 connection.py:143(_check_writable)
        1  0.000  0.000  0.000  0.000 connection.py:182(send_bytes)
        1  0.000  0.000  0.000  0.000 connection.py:284(_send_bytes)
        1  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
        1  0.000  0.000  0.000  0.000 context.py:237(get_context)
        1  0.000  0.000  0.000  0.000 context.py:65(Lock)
  8000000  2.343  0.000  4.931  0.000 hashlib.py:152(__hash_new)
        1  0.000  0.000  0.000  0.000 process.py:37(current_process)
        1  0.000  0.000  0.000  0.000 random.py:480(choices)
        1  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
       11  0.000  0.000  0.000  0.000 shared_memory.py:204(buf)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
        1  0.000  0.000  0.000  0.000 shared_memory.py:278(<lambda>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
        2  0.000  0.000  0.000  0.000 shared_memory.py:371(_get_packing_format)
        1  0.000  0.000  0.000  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
        1  0.000  0.000  0.000  0.000 shared_memory.py:402(_set_packing_format_and_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:424(__getitem__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:441(__setitem__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
       10  0.000  0.000  0.000  0.000 shared_memory.py:505(_offset_data_start)
        7  0.000  0.000  0.000  0.000 shared_memory.py:511(_offset_packing_formats)
        3  0.000  0.000  0.000  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        1  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        1  0.000  0.000  0.000  0.000 synchronize.py:94(__enter__)
        1  0.000  0.000  0.000  0.000 synchronize.py:97(__exit__)
        1  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        1  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        1  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        1  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
        1  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        1  0.000  0.000  0.000  0.000 threading.py:243(__init__)
        1  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
        1  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
        1  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
        1  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
        1  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
        1  0.000  0.000  0.001  0.001 threading.py:295(wait)
        1  0.000  0.000  0.000  0.000 threading.py:562(__init__)
        1  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        1  0.000  0.000  0.001  0.001 threading.py:611(wait)
        1  0.000  0.000  0.000  0.000 threading.py:811(_newname)
        1  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        1  0.000  0.000  0.001  0.001 threading.py:945(start)
        1  0.000  0.000  0.000  0.000 util.py:48(debug)
  8000000  2.588  0.000  2.588  0.000 {built-in method _hashlib.new}
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        7  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.unpack_from}
        2  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.WriteFile}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  20.794  20.794 {built-in method builtins.exec}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.getattr}
       11  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
        8  0.000  0.000  0.000  0.000 {built-in method builtins.len}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
        8  0.000  0.000  0.000  0.000 {built-in method math.floor}
        1  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
        1  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
        1  0.000  0.000  0.000  0.000 {method '__enter__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
        4  0.001  0.000  0.001  0.000 {method 'acquire' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
        1  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
        3  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
        3  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
  8000000  2.793  0.000  2.793  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
  8000004  0.766  0.000  0.766  0.000 {method 'encode' of 'str' objects}
  8000003  0.966  0.000  0.966  0.000 {method 'join' of 'str' objects}
        8  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
        1  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
        2  0.000  0.000  0.000  0.000 {method 'rstrip' of 'bytes' objects}
  8000000  0.784  0.000  0.784  0.000 {method 'update' of '_hashlib.HASH' objects}
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
84541560 23.5305474 amongamongamong
         48000204 function calls in 22.861 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
        1  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        1  0.000  0.000  22.860  22.860 <string>:1(<module>)
        1  0.000  0.000  0.000  0.000 MultiProcessorPipe2.py:17(__init__)
        1  10.823  10.823  22.860  22.860 MultiProcessorPipe2.py:51(run)
        1  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        1  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
        1  0.000  0.000  0.000  0.000 connection.py:143(_check_writable)
        1  0.000  0.000  0.000  0.000 connection.py:182(send_bytes)
        1  0.000  0.000  0.000  0.000 connection.py:284(_send_bytes)
        1  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
        1  0.000  0.000  0.000  0.000 context.py:237(get_context)
        1  0.000  0.000  0.000  0.000 context.py:65(Lock)
  8000000  2.313  0.000  4.896  0.000 hashlib.py:152(__hash_new)
        1  0.000  0.000  0.000  0.000 process.py:37(current_process)
        1  0.000  0.000  0.000  0.000 random.py:480(choices)
        1  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
       11  0.000  0.000  0.000  0.000 shared_memory.py:204(buf)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
        1  0.000  0.000  0.000  0.000 shared_memory.py:278(<lambda>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
        2  0.000  0.000  0.000  0.000 shared_memory.py:371(_get_packing_format)
        1  0.000  0.000  0.000  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
        1  0.000  0.000  0.000  0.000 shared_memory.py:402(_set_packing_format_and_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:424(__getitem__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:441(__setitem__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
       10  0.000  0.000  0.000  0.000 shared_memory.py:505(_offset_data_start)
        7  0.000  0.000  0.000  0.000 shared_memory.py:511(_offset_packing_formats)
        3  0.000  0.000  0.000  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        1  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        1  0.000  0.000  0.000  0.000 synchronize.py:94(__enter__)
        1  0.000  0.000  0.000  0.000 synchronize.py:97(__exit__)
        1  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        1  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        1  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        1  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
        1  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        1  0.000  0.000  0.000  0.000 threading.py:243(__init__)
        1  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
        1  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
        1  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
        1  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
        1  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
        1  0.000  0.000  0.001  0.001 threading.py:295(wait)
        1  0.000  0.000  0.000  0.000 threading.py:562(__init__)
        1  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        1  0.000  0.000  0.001  0.001 threading.py:611(wait)
        1  0.000  0.000  0.000  0.000 threading.py:811(_newname)
        1  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        1  0.000  0.000  0.001  0.001 threading.py:945(start)
        1  0.000  0.000  0.000  0.000 util.py:48(debug)
  8000000  2.583  0.000  2.583  0.000 {built-in method _hashlib.new}
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        7  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.unpack_from}
        2  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.WriteFile}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  22.861  22.861 {built-in method builtins.exec}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.getattr}
       11  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
        8  0.000  0.000  0.000  0.000 {built-in method builtins.len}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
        8  0.000  0.000  0.000  0.000 {built-in method math.floor}
        1  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
        1  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
        1  0.000  0.000  0.000  0.000 {method '__enter__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
        4  0.001  0.000  0.001  0.000 {method 'acquire' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
        1  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
        3  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
        3  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
  8000000  4.579  0.000  4.579  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
  8000004  0.768  0.000  0.768  0.000 {method 'encode' of 'str' objects}
  8000003  0.997  0.000  0.997  0.000 {method 'join' of 'str' objects}
        8  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
        1  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
        2  0.000  0.000  0.000  0.000 {method 'rstrip' of 'bytes' objects}
  8000000  0.796  0.000  0.796  0.000 {method 'update' of '_hashlib.HASH' objects}
Enter Password: q
Done
import itertools
import hashlib
import multiprocessing.shared_memory
import matplotlib as plt
import time
import multiprocessingÂ
import threading
import cProfile
import math
from multiprocessing import shared_memory
#Converges the geometric series for when starting at 1
def geometricSeries(a: int, r: int, n: int):
    return a * r * ((r ** n - 1) // (r - 1))
class CancellationToken:
   def __init__(self):
       self.is_cancelled = False
   def cancel(self):
       self.is_cancelled = True
def wait(event, token):
    event.wait()
    token.cancel()
def run(perms, arr, algorithm, password, words, lock, conn, event):
    count = 0
    token = CancellationToken()
    thread = threading.Thread(target=wait, args=[event, token])
    thread.start()
    for p in perms:
        word = b''.join(p)
        hash = hashlib.new(algorithm, word)
        for w in words:
            clone = hash.copy()
            clone.update(w)
            count += 1
            if clone.digest() == password:
                event.set()
                with lock:
                    arr[2] = word + w
                    arr[1] = True
            elif token.is_cancelled: break
        if token.is_cancelled: break
    with lock:
        arr[0] = arr[0] + count
        conn.send_bytes(b'\x00')
    #thread.join()
def multiProcessor2(wordLimit: int, words: list, password: bytes, algorithm: str):
    start = time.time_ns()
    arr = shared_memory.ShareableList([0, False, "\0" * 100])
    lock = multiprocessing.Lock()
    recv, send = multiprocessing.Pipe()
    event = multiprocessing.Event()
    for i in range(1, wordLimit + 1):
        perms = itertools.product(words, repeat=i - 1)
        wordsLen = len(words)
        size = math.ceil(wordsLen / multiprocessing.cpu_count())
        processes = []
        for j in range(0, wordsLen, size):
            p = multiprocessing.Process(target=run,args=[perms, arr, algorithm, password, words[j : j + size], lock, send, event])
            p.start()
            processes.append(p)
            if arr[1]: break
        completed = 0
        while completed != len(processes):
            recv.recv_bytes()
            if arr[1]:
                break
            completed += 1
        event.set()
        for p in processes:
            p.join()
        event.clear()
        if arr[1]:
            break
    recv.close()
    send.close()
    return arr[0], (time.time_ns() - start) / 1e9, arr[2].decode()
       Â
if __name__ == "__main__":
    wordLimit = 3
    dictonaryName = "MediumDictionary.txt"
    hashAlgorithms = ['sha256', 'sha512']
    f = open(dictonaryName, "r")
    words = f.read().splitlines()
    f.close()
    maxCount = geometricSeries(1,len(words),wordLimit - 1) + ((len(words) ** wordLimit) // multiprocessing.cpu_count()) * 11
    print(f"Longest Password is {words[-1] * wordLimit} and will take around {maxCount} iterations and around {round(maxCount * 2.5e-7,2)} seconds")
    password = input("Enter Password: ")
    words = [w.encode() for w in words]
    while password != "q":
        for h in hashAlgorithms:
            hash = hashlib.new(h)
            hash.update(password.encode()) #Hashes the password
            print(f"{h.capitalize()} Hash: {hash.hexdigest()}") #Prints nice Hex
            breakCount, breakTime, value = multiProcessor2(wordLimit, words, hash.digest(), h)
            #cProfile.run('multiProcessor2(wordLimit, words, hash.digest(), h)')
            print(breakCount, breakTime, value)
            recv, send = multiprocessing.Pipe() #amongamongbut
            event = multiprocessing.Event()
            cProfile.run('run(itertools.product(words, repeat=2), shared_memory.ShareableList([0, False, 0]), h, password, words[0 : 32], multiprocessing.Lock(), send, event)')
            event.set()
        password = input("Enter Password: ")
    print("Done")Â
Longest Password is amongamongamong and will take around 86188000 iterations and around 21.55 seconds
Enter Password: amongamongamong
Sha256 Hash: 922f052e4cc8f014de935fb51ed139c1e21d091accf6c9d1f89f2c41310e0969
94068503 13.3223273 amongamongamong
         24750204 function calls in 10.606 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
        1  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        1  0.000  0.000  10.606  10.606 <string>:1(<module>)
        1  0.000  0.000  0.000  0.000 MultiProcessorPipe2.py:17(__init__)
        1  5.392  5.392  10.606  10.606 MultiProcessorPipe2.py:27(run)
        1  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        1  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
        1  0.000  0.000  0.000  0.000 connection.py:143(_check_writable)
        1  0.000  0.000  0.000  0.000 connection.py:182(send_bytes)
        1  0.000  0.000  0.000  0.000 connection.py:284(_send_bytes)
        1  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
        1  0.000  0.000  0.000  0.000 context.py:237(get_context)
        1  0.000  0.000  0.000  0.000 context.py:65(Lock)
   250000  0.081  0.000  0.170  0.000 hashlib.py:152(__hash_new)
        1  0.000  0.000  0.000  0.000 process.py:37(current_process)
        1  0.000  0.000  0.000  0.000 random.py:480(choices)
        1  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
       11  0.000  0.000  0.000  0.000 shared_memory.py:204(buf)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
        1  0.000  0.000  0.000  0.000 shared_memory.py:278(<lambda>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
        2  0.000  0.000  0.000  0.000 shared_memory.py:371(_get_packing_format)
        1  0.000  0.000  0.000  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
        1  0.000  0.000  0.000  0.000 shared_memory.py:402(_set_packing_format_and_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:424(__getitem__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:441(__setitem__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
       10  0.000  0.000  0.000  0.000 shared_memory.py:505(_offset_data_start)
        7  0.000  0.000  0.000  0.000 shared_memory.py:511(_offset_packing_formats)
        3  0.000  0.000  0.000  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        1  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        1  0.000  0.000  0.000  0.000 synchronize.py:94(__enter__)
        1  0.000  0.000  0.000  0.000 synchronize.py:97(__exit__)
        1  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        1  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        1  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        1  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
        1  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        1  0.000  0.000  0.000  0.000 threading.py:243(__init__)
        1  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
        1  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
        1  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
        1  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
        1  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
        1  0.000  0.000  0.001  0.001 threading.py:295(wait)
        1  0.000  0.000  0.000  0.000 threading.py:562(__init__)
        1  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        1  0.000  0.000  0.001  0.001 threading.py:611(wait)
        1  0.000  0.000  0.000  0.000 threading.py:811(_newname)
        1  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        1  0.000  0.000  0.001  0.001 threading.py:945(start)
        1  0.000  0.000  0.000  0.000 util.py:48(debug)
   250000  0.088  0.000  0.088  0.000 {built-in method _hashlib.new}
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        7  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.unpack_from}
        2  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.WriteFile}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  10.606  10.606 {built-in method builtins.exec}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.getattr}
       11  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
        8  0.000  0.000  0.000  0.000 {built-in method builtins.len}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
        8  0.000  0.000  0.000  0.000 {built-in method math.floor}
        1  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
        1  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
        1  0.000  0.000  0.000  0.000 {method '__enter__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
        4  0.001  0.000  0.001  0.000 {method 'acquire' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
        1  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
        3  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
  8000000  1.404  0.000  1.404  0.000 {method 'copy' of '_hashlib.HASH' objects}
        3  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
  8000000  2.945  0.000  2.945  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
        4  0.000  0.000  0.000  0.000 {method 'encode' of 'str' objects}
   250000  0.033  0.000  0.033  0.000 {method 'join' of 'bytes' objects}
        3  0.000  0.000  0.000  0.000 {method 'join' of 'str' objects}
        8  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
        1  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
        2  0.000  0.000  0.000  0.000 {method 'rstrip' of 'bytes' objects}
  8000000  0.661  0.000  0.661  0.000 {method 'update' of '_hashlib.HASH' objects}
Sha512 Hash: 0c0861dc3779cc1e7cc7b1edcdd1864617f3f4c67656724e47c94033ced9f1c0750807a20a7283df8cc52c27d3814fd5200d9ab27d308aaa7df550a70f155249
90725757 16.3540242 amongamongamong
         24750204 function calls in 12.229 seconds
   Ordered by: standard name
   ncalls tottime percall cumtime percall filename:lineno(function)
        1  0.000  0.000  0.000  0.000 <frozen importlib._bootstrap>:405(parent)
        1  0.000  0.000  12.228  12.228 <string>:1(<module>)
        1  0.000  0.000  0.000  0.000 MultiProcessorPipe2.py:17(__init__)
        1  5.357  5.357  12.228  12.228 MultiProcessorPipe2.py:27(run)
        1  0.000  0.000  0.000  0.000 _weakrefset.py:85(add)
        1  0.000  0.000  0.000  0.000 connection.py:135(_check_closed)
        1  0.000  0.000  0.000  0.000 connection.py:143(_check_writable)
        1  0.000  0.000  0.000  0.000 connection.py:182(send_bytes)
        1  0.000  0.000  0.000  0.000 connection.py:284(_send_bytes)
        1  0.000  0.000  0.000  0.000 context.py:197(get_start_method)
        1  0.000  0.000  0.000  0.000 context.py:237(get_context)
        1  0.000  0.000  0.000  0.000 context.py:65(Lock)
   250000  0.081  0.000  0.171  0.000 hashlib.py:152(__hash_new)
        1  0.000  0.000  0.000  0.000 process.py:37(current_process)
        1  0.000  0.000  0.000  0.000 random.py:480(choices)
        1  0.000  0.000  0.000  0.000 random.py:493(<listcomp>)
        1  0.000  0.000  0.000  0.000 random.py:808(randbytes)
        1  0.000  0.000  0.000  0.000 secrets.py:34(token_bytes)
        1  0.000  0.000  0.000  0.000 secrets.py:48(token_hex)
        1  0.000  0.000  0.000  0.000 shared_memory.py:185(__del__)
       11  0.000  0.000  0.000  0.000 shared_memory.py:204(buf)
        1  0.000  0.000  0.000  0.000 shared_memory.py:223(close)
        1  0.000  0.000  0.000  0.000 shared_memory.py:278(<lambda>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:284(_extract_recreation_code)
        1  0.000  0.000  0.000  0.000 shared_memory.py:298(__init__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:301(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:310(<genexpr>)
        1  0.000  0.000  0.000  0.000 shared_memory.py:319(<listcomp>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:346(<genexpr>)
        4  0.000  0.000  0.000  0.000 shared_memory.py:352(<genexpr>)
        2  0.000  0.000  0.000  0.000 shared_memory.py:371(_get_packing_format)
        1  0.000  0.000  0.000  0.000 shared_memory.py:387(_get_back_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:40(_make_filename)
        1  0.000  0.000  0.000  0.000 shared_memory.py:402(_set_packing_format_and_transform)
        1  0.000  0.000  0.000  0.000 shared_memory.py:424(__getitem__)
        1  0.000  0.000  0.000  0.000 shared_memory.py:441(__setitem__)
        2  0.000  0.000  0.000  0.000 shared_memory.py:490(_format_size_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:495(_format_packing_metainfo)
        2  0.000  0.000  0.000  0.000 shared_memory.py:500(_format_back_transform_codes)
       10  0.000  0.000  0.000  0.000 shared_memory.py:505(_offset_data_start)
        7  0.000  0.000  0.000  0.000 shared_memory.py:511(_offset_packing_formats)
        3  0.000  0.000  0.000  0.000 shared_memory.py:515(_offset_back_transform_codes)
        1  0.000  0.000  0.000  0.000 shared_memory.py:75(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:121(_make_name)
        1  0.000  0.000  0.000  0.000 synchronize.py:168(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:50(__init__)
        1  0.000  0.000  0.000  0.000 synchronize.py:90(_make_methods)
        1  0.000  0.000  0.000  0.000 synchronize.py:94(__enter__)
        1  0.000  0.000  0.000  0.000 synchronize.py:97(__exit__)
        1  0.000  0.000  0.000  0.000 tempfile.py:143(rng)
        1  0.000  0.000  0.000  0.000 tempfile.py:154(__next__)
        1  0.000  0.000  0.000  0.000 threading.py:1206(daemon)
        1  0.000  0.000  0.000  0.000 threading.py:1324(_make_invoke_excepthook)
        1  0.000  0.000  0.000  0.000 threading.py:1453(current_thread)
        1  0.000  0.000  0.000  0.000 threading.py:243(__init__)
        1  0.000  0.000  0.000  0.000 threading.py:271(__enter__)
        1  0.000  0.000  0.000  0.000 threading.py:274(__exit__)
        1  0.000  0.000  0.000  0.000 threading.py:280(_release_save)
        1  0.000  0.000  0.000  0.000 threading.py:283(_acquire_restore)
        1  0.000  0.000  0.000  0.000 threading.py:286(_is_owned)
        1  0.000  0.000  0.000  0.000 threading.py:295(wait)
        1  0.000  0.000  0.000  0.000 threading.py:562(__init__)
        1  0.000  0.000  0.000  0.000 threading.py:575(is_set)
        1  0.000  0.000  0.001  0.001 threading.py:611(wait)
        1  0.000  0.000  0.000  0.000 threading.py:811(_newname)
        1  0.000  0.000  0.000  0.000 threading.py:856(__init__)
        1  0.000  0.000  0.001  0.001 threading.py:945(start)
        1  0.000  0.000  0.000  0.000 util.py:48(debug)
   250000  0.090  0.000  0.090  0.000 {built-in method _hashlib.new}
        1  0.000  0.000  0.000  0.000 {built-in method _struct.calcsize}
        7  0.000  0.000  0.000  0.000 {built-in method _struct.pack_into}
        4  0.000  0.000  0.000  0.000 {built-in method _struct.unpack_from}
        2  0.000  0.000  0.000  0.000 {built-in method _thread.allocate_lock}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.get_ident}
        1  0.000  0.000  0.000  0.000 {built-in method _thread.start_new_thread}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CloseHandle}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.CreateFileMapping}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.GetLastError}
        1  0.000  0.000  0.000  0.000 {built-in method _winapi.WriteFile}
        1  0.000  0.000  0.000  0.000 {built-in method binascii.hexlify}
        1  0.000  0.000  12.229  12.229 {built-in method builtins.exec}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.getattr}
       11  0.000  0.000  0.000  0.000 {built-in method builtins.isinstance}
        8  0.000  0.000  0.000  0.000 {built-in method builtins.len}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.next}
        1  0.000  0.000  0.000  0.000 {built-in method builtins.sum}
        8  0.000  0.000  0.000  0.000 {built-in method math.floor}
        1  0.000  0.000  0.000  0.000 {built-in method nt.getpid}
        1  0.000  0.000  0.000  0.000 {built-in method nt.urandom}
        1  0.000  0.000  0.000  0.000 {method 'GetOverlappedResult' of '_winapi.Overlapped' objects}
        1  0.000  0.000  0.000  0.000 {method '__enter__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__enter__' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_multiprocessing.SemLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.RLock' objects}
        1  0.000  0.000  0.000  0.000 {method '__exit__' of '_thread.lock' objects}
        4  0.000  0.000  0.000  0.000 {method 'acquire' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'add' of 'set' objects}
        1  0.000  0.000  0.000  0.000 {method 'append' of 'collections.deque' objects}
        3  0.000  0.000  0.000  0.000 {method 'append' of 'list' objects}
        1  0.000  0.000  0.000  0.000 {method 'close' of 'mmap.mmap' objects}
  8000000  1.412  0.000  1.412  0.000 {method 'copy' of '_hashlib.HASH' objects}
        3  0.000  0.000  0.000  0.000 {method 'decode' of 'bytes' objects}
  8000000  4.549  0.000  4.549  0.000 {method 'digest' of '_hashlib.HASH' objects}
        1  0.000  0.000  0.000  0.000 {method 'disable' of '_lsprof.Profiler' objects}
        4  0.000  0.000  0.000  0.000 {method 'encode' of 'str' objects}
   250000  0.035  0.000  0.035  0.000 {method 'join' of 'bytes' objects}
        3  0.000  0.000  0.000  0.000 {method 'join' of 'str' objects}
        8  0.000  0.000  0.000  0.000 {method 'random' of '_random.Random' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of '_thread.lock' objects}
        1  0.000  0.000  0.000  0.000 {method 'release' of 'memoryview' objects}
        1  0.000  0.000  0.000  0.000 {method 'rpartition' of 'str' objects}
        2  0.000  0.000  0.000  0.000 {method 'rstrip' of 'bytes' objects}
  8000000  0.703  0.000  0.703  0.000 {method 'update' of '_hashlib.HASH' objects}
Enter Password: q
Done
With the deadline quickly approaching I ended my optimization journey with one last optimization. As part of this assignment we were allowed to use the length of the inputted password to quickly decrypt it. I believe we were allowed to do this since the intended solution was to iterate through every possible combination and this would significantly speed up the process. An example of this is in the first attempt were after using the length with the soon to be mentioned optimizations turned the ~3 minute run time to around ~11 seconds. Said other optimizations were also sorting the word list by length before trying to decrypt it as this let me possible removed all permutations and even skip over processes. The last change was also adding the graphing portion of the assignment. In terms of performance the length filter makes it extremely difficult to know which word combination takes the longest however I have not seen any take more then 10 seconds and the longest was ~8 seconds which was easteasteast.
import itertools
import hashlib
import multiprocessing.shared_memory
import matplotlib.pyplot as plt
import matplotlib
import time
import multiprocessingÂ
import threading
import cProfile #Used for profiling
import math
from multiprocessing import shared_memory
import sys
#An Iterative approch to the problem however is not used due to a faster implmentation
def hashAttack(wordLimit: int, words: list, password: bytes, algorithm: str, passwordLen : int):
    start = time.time_ns()
    minLen = len(words[0])
    maxLen = len(words[-1])
    count = 0
    for i in range(1, wordLimit + 1):       Â
        if not isBetween(minLen * (i + 1), passwordLen, maxLen * (i + 1)):
            continue
        perms = itertools.product(words, repeat=i)
        for p in perms:
            test = b''.join(p)
            if passwordLen != len(test):
                continue
            hash = hashlib.new(algorithm)
            hash.update(test)
            count += 1
            if (hash.digest() == password):
                return count, (time.time_ns() - start) / 1e9, test.decode()
    return None, None
#Converges the geometric series for when starting at 1
def geometricSeries(a: int, r: int, n: int):
    return a * r * ((r ** n - 1) // (r - 1))
#Will return if the value is in between two other values, inclusive
def isBetween(min, val, max):
    return min <= val and val <= max
#Used as a shared boolean between process and thread
class CancellationToken:
   def __init__(self):
       self.is_cancelled = False
   def cancel(self):
       self.is_cancelled = True
#Will wait until a provided event is trigered then sets the token to True
def wait(event, token):
    event.wait()
    token.cancel()
#Takes a chunk of data then tests to see if any are the password, will stop when the event is set
def run(perms, arr, algorithm, password, words, lock, conn, event, passwordLen):
    count = 0
    token = CancellationToken()
    thread = threading.Thread(target=wait, args=[event, token]) #Starts the thread to see if the event is set
    thread.start()
    minLen = len(words[0])
    maxLen = len(words[-1])
    #For ever previous permutation
    for p in perms:
        word = b''.join(p)
        if not isBetween(len(word) + minLen, passwordLen, len(word) + maxLen):
            continue
        #Add each word to the end
        for w in words:
            test = word + w
            if passwordLen != len(test):
                continue
            hash = hashlib.new(algorithm, test)
            count += 1
            if hash.digest() == password:
                event.set() #Tells all other process to end
                with lock:
                    arr[2] = test
                    arr[1] = True
            elif token.is_cancelled: break
        if token.is_cancelled: break
    with lock:
        arr[0] = arr[0] + count
        conn.send_bytes(b'\x00') #Signal that the process has ended
    thread.join() #Waits for the thread to end
#Takes a list of words and a hashed password and will try to decode said password
def multiProcessor2(wordLimit: int, words: list, password: bytes, algorithm: str, passwordLen : int):
    start = time.time_ns()
    minLen = len(words[0])
    maxLen = len(words[-1])
    arr = shared_memory.ShareableList([0, False, "\0" * (maxLen * wordLimit)]) #Shared output among process
    lock = multiprocessing.Lock() #Shared lock among process to acess the shared output safely
    recv, send = multiprocessing.Pipe() #Signal to know when a process finishes
    event = multiprocessing.Event() #Event to tell all process to finish
    #For every wordlimt
    for i in range(0, wordLimit):
        if not isBetween(minLen * (i + 1), passwordLen, maxLen * (i + 1)):
            continue
        perms = itertools.product(words, repeat = i) #Get all permutations of the previous wordlimt
        wordsLen = len(words)
        size = math.ceil(wordsLen / multiprocessing.cpu_count()) #Chunk length of words to split
        processes = [] #Holds all the processes
        for j in range(0, wordsLen, size):
            subArr = words[j : j + size]
            if not isBetween((minLen * i) + len(subArr[0]), passwordLen, (maxLen * i) + len(subArr[-1])):
                continue
            p = multiprocessing.Process(target=run,args=[perms, arr, algorithm, password, subArr, lock, send, event, passwordLen])
            p.start()
            processes.append(p)
            if arr[1]: break #If found
           Â
        completed = 0 #Counts how many processes have finished
        while completed != len(processes):
            recv.recv_bytes() #Waits until a process finishes
            if arr[1]: #If value is found
                break
            completed += 1
        event.set() #Tells all the processes to finish
        #Waits until all process have finished
        for p in processes:
            p.join()
        event.clear() #Resets the event to do again if needed
        if arr[1]:
            break
    #Close Connections
    recv.close()
    send.close()
    return arr[0], (time.time_ns() - start) / 1e9, arr[2].decode() #returns (count, time, password)
#Takes a password and hash algorithm and will try to break it
def codeAndDecode(algorithm, password, wordLimit, words, passwordLen, printing=False):Â Â Â
    hash = hashlib.new(algorithm)
    hash.update(password) #Hashes the password
    if printing:
        print(f"{algorithm.capitalize()} Hash: {hash.hexdigest()}") #Prints nice Hex
    return multiProcessor2(wordLimit, words, hash.digest(), algorithm, passwordLen) Â
#Takes a axis and will add data to it depending on the type
def setUpAxes(data, type, ax):
    index = -1
    if type == 'Count':
        index = 0
    elif type == 'Time (sec)':
        index = 1
    data = sorted(data, key = lambda x: x[-1]) #Sorts data based on complexity
    x = []
    y = []
    for i in range(0, len(data)):
        d = data[i]
        x.append(i + 1)
        y.append(d[index])
    ax.plot(x,y,'o-')
#Main function
if __name__ == "__main__":
    wordLimit = 3
    dictonaryName = "MediumDictionary.txt"
    hashAlgorithms = list(hashlib.algorithms_available) #Comment the line below to see all hashes
    hashAlgorithms = ['sha256', 'sha512']
    hashAlgorithms = [h for h in hashAlgorithms if "shake" not in h] #Removed shake hashes which require a length to hash
    f = open(dictonaryName, "r")
    words = f.read().splitlines() #Reads the dictonary
    f.close()
    words = sorted(words, key=len) #Sorts the dictonary
    data = [[] for _ in hashAlgorithms] #Initializes data
    perms = ["".join(p) for i in range(1, wordLimit + 1) for p in itertools.product(words, repeat=i)] #Combines all possible iterations, I know this isn't memory efficent but is better then doing iterativly for how often I use it
    password = input("Enter Password: ")
    words = [w.encode() for w in words] #Encodes all the words to bytes
    #While the user is inputting passwords
    while password != "q":
        count = perms.index(password) + 1 #Get the complexity
        password = password.encode()
        #Decodes the password using different algorithms
        for i in range(0, len(hashAlgorithms)):
            ret = codeAndDecode(hashAlgorithms[i], password, wordLimit, words, len(password), True) + (count,)
            data[i].append(ret)
            print(ret)
        password = input("Enter Password: ")
    inputedData = data[0].copy() #Copies the dataÂ
    count = 0
    total = len(inputedData) * 10 * len(hashAlgorithms) #How much data will be calculated, used for percentage
    for a in range(0, len(inputedData)):
        d = inputedData[a] #Gets the data
        #For every value that is 5 to the left and 5 to the right
        for i in range(d[-1] - 5, d[-1] + 6):
            if i == d[-1]: #Not current value
                continue
            password = perms[i - 1].encode()
            index = perms.index(perms[i - 1]) + 1 #Get the complexity
            for j in range(0, len(hashAlgorithms)):
                count += 1
                ret = codeAndDecode(hashAlgorithms[j], password, wordLimit, words, len(password)) + (index,)
                data[j].append(ret)
                #Prints the percentage
                sys.stdout.write(f"\rComputing Specific Values Currently: {round(count / total * 100,2)}%")
                sys.stdout.flush()
    print() #Resets printing to function properly
    #Makes all the plots
    fig, axs = plt.subplots(ncols=2, nrows=1, layout='constrained')
    axs = axs.flatten()
    ylabels = ['Time (sec)', 'Count']
    for a in range(0, len(axs)):
        ax = axs[a]
        label = ylabels[a]
        ax.set_title(f"Complexity vs. {label} to Crack Different Hashes with a Dictonary Size of {len(words)}")
        ax.grid(False)
        ax.set_xlabel("Complexity")
        ax.set_ylabel(label)
        ax.set_xticks(list(range(1, len(data[0]) + 1)))
        ax.set_xticklabels([d[2] for d in sorted(data[0], key = lambda x: x[-1])], rotation='vertical')
        for i in range(0, len(hashAlgorithms)):
            algorithm = hashAlgorithms[i]
            setUpAxes(data[i], label, ax)
    fig.legend(loc='outside center right', labels=hashAlgorithms) #The legend of the plots
    plt.ticklabel_format(style='plain', axis='y') #Removes the 1e6 from the graphs
    plt.show(block=True) #Shows the plots
    print("Done")Â