根据一些固定数据和其他数据的所有排列,从某个字符串开始计算 sha256 哈希

Calculate sha256 hash starting with some string based on some fixed data and all permutations of other data

我需要计算以某个字符串开头的哈希值。 我的输入是:

  1. 其他哈希(固定)
  2. 一些可变数据占用 5 个字节,我需要以某种方式准备这些数据,以便结果哈希以例如开头。 'ABC'

我对 Python 有点陌生,我想出了这个丑陋的解决方案(在函数计算中)。为了加快处理速度,我使用执行程序 运行 在所有内核上执行此操作。

谁能帮我想办法让这个函数 'calculate' 不那么难看?如何做得更好?如何遍历可变参数数据的 5 个字节的所有排列?最后,我在这里做错了什么或非 pythonic?

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

为了使您的计算函数更具可读性,我建议更改您执行操作的顺序。
如果你计算所有的字母然后构建你的字符串,代码看起来会更清晰并且 更具可读性。作为副产品,它将 运行 更快。

目前您正在关注这个序列

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

如果你

它会看起来更干净
1
calculate next letter
    calculate next letter
        calculate next letter
            ......
            make string
            append salt
            append letters
            hash string and compare value

我遵循一个简单的规则, 如果我必须多次编写相同的指令,那么 一种简化程序的方法

你的 print() 语句在我尝试时抛出错误。 我相信您想要显示十六进制结果。你将需要这样的东西

print('success!, x = %02x, y = %02x, z = %02x, a = %02x, b = %02x' % (x, y, z, a, b))

还有很多格式化字符串的方法Some can be found here.

您已经用 8 个值对数组 data[] 进行了硬编码,并为您的数组添加了一个 for-range 循环 calculate() 功能有助于为您的 cpu 核心分配工作负载。这限制了你的代码 运行最多 8 个内核。

我可以建议让 ProcessPoolExecutor().map 为您做这件事。它会让更多 无需系统知识即可有效使用不同的硬件设置。

calculate() 函数中将 for x in range(pars[0],pars[1]): 替换为 x = pars 并更正缩进,然后当您调用 executor.map 时使用 range() 像这样

res = executor.map(calculate, range(256))

它将通过每个过程 1 次迭代,直到所有过程都完成。 More information about executor.map can be found here.

这是经过上述更改的代码

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