Reputation: 1207
I need to calculate hash which starts with some string. My input is:
I am somewhat new in Python, and I came up with this ugly solution (in function calculate). To speed up processing I use executors to run this on all cores.
Can someone help me figure out to make this function 'calculate' less ugly? How to do it better? How to iterate through all permutations of 5 bytes of my variadic data? And finally, what do I do wrong or non-pythonic here?
import hashlib
import concurrent.futures
import copy
input_hash = [0x79,0xaf,0x37,0xc4,0x32,0x8e,0x7b,0x67,0xb1,0xfa,0x76,0x36,0x11,0x21,0xa4,0xdd,0x6c,0x29,0xf0,0x6b,0x50,0x67,0x57,0x16,0x0b,0xee,0x30,0x32,0x2a,0x05,0x9e,0x75]
def calculate(pars):
print(pars)
for x in range(pars[0],pars[1]):
whole = []
whole.extend(bytearray(input_hash))
whole.extend(bytes([x]))
copy1 = copy.deepcopy(whole)
for y in range(256):
whole = copy.deepcopy(copy1)
whole.extend(bytes([y]))
copy2 = copy.deepcopy(whole)
for z in range(256):
whole = copy.deepcopy(copy2)
whole.extend(bytes([z]))
copy3 = copy.deepcopy(whole)
for a in range(256):
whole = copy.deepcopy(copy3)
whole.extend(bytes([a]))
copy4 = copy.deepcopy(whole)
for b in range(256):
whole = copy.deepcopy(copy4)
whole.extend(bytes([b]))
whole.extend(bytes([0]*2))
m = hashlib.sha256()
m.update(bytearray(whole))
d = m.hexdigest()
if d.startswith('ABC'):
print('success!, x = %, y = %, z = %, a = %, b = %' % x, y, z, a, b)
return
data = [(0,33),(33,67),(67,101),(101,135),(135,169),(169,203),(203,237),(237,256)]
with concurrent.futures.ProcessPoolExecutor() as executor:
res = executor.map(calculate, data)
for r in res:
pass
Upvotes: 1
Views: 373
Reputation: 186
In order to make your calculate function more readable I would suggest changing the order you do things.
if you calculate all the letters then build your string, the code would look a lot cleaner and
more readable. As a byproduct it will run faster to.
Currently you are following this sequence
make string,
append salt
1
copy string
calculate next letter
append letter to string
2
copy string
calculate next letter
append letter to string
repeat 3 more time.
hash string and compare value
it would look cleaner if you
1
calculate next letter
calculate next letter
calculate next letter
......
make string
append salt
append letters
hash string and compare value
I follow a simple rule, If I have to write the same instructions more than twice, there a way to simplify the procedure
Your print()
statement throws an error when I tried it.
I believe your wanting to display the hex results. You will need something like this
print('success!, x = %02x, y = %02x, z = %02x, a = %02x, b = %02x' % (x, y, z, a, b))
There are many other methods to format strings Some can be found here.
You have hard coded an array data[]
with 8 values and added a for-range loop to your
calculate()
function to help split-up the workload for your cpu cores. this limits your code
to running on a maximum of 8 cores.
May I suggest letting the ProcessPoolExecutor().map
do this for you. it will make more
effective use of different hardware setups without you needing knowledge of the systems.
In the calculate()
function replace the for x in range(pars[0],pars[1]):
with x = pars
and correct the indents, then when you call executor.map
use a range()
like so
res = executor.map(calculate, range(256))
it will pass each process 1 iteration until all are complete. More information about executor.map can be found here.
Here is the code with the above mentioned changes
import hashlib
import concurrent.futures
input_hash = [0x79,0xaf,0x37,0xc4,0x32,0x8e,0x7b,0x67,0xb1,0xfa,0x76,0x36,0x11,0x21,0xa4,0xdd,0x6c,0x29,0xf0,0x6b,0x50,0x67,0x57,0x16,0x0b,0xee,0x30,0x32,0x2a,0x05,0x9e,0x75]
def calculate(pars):
print(pars)
x = pars
for y in range(256):
for z in range(256):
for a in range(256):
for b in range(256):
whole = []
whole.extend(bytearray(input_hash))
whole.extend(bytes([x]))
whole.extend(bytes([y]))
whole.extend(bytes([z]))
whole.extend(bytes([a]))
whole.extend(bytes([b]))
whole.extend(bytes([0]*2))
m = hashlib.sha256()
m.update(bytearray(whole))
d = m.hexdigest()
if d.startswith('ABC'):
print('success!, x = %02x, y = %02x, z = %02x, a = %02x, b = %02x' % (x, y, z, a, b))
return
with concurrent.futures.ProcessPoolExecutor() as executor:
res = executor.map(calculate, range(256))
for r in res:
pass
Upvotes: 1