哈希(hash)函数生成的哈希值不一致问题

4

我有一个函数,它生成一个带有一些数据的

def new_block(self, proof, previous_hash=None):

    ...

    block = {
        'message': 'New Block Forged',
        'index': len(self.chain) + 1,
        'transactions': self.current_transactions,
        'proof': proof,
        'previous_hash': previous_hash, or self.hash_block(self.chain[-1]),
        'timestamp': response.tx_time or time(),
    }

self.chain是块所在的列表。函数中传入了previous_hash(前一个块的哈希值),并创建了一个时间戳。不必过于关注实际数据的细节(可能存在问题,但这更与hash()函数有关,而非数据的操作)。

接下来,我对块进行哈希运算,并将其添加到块中:

block['hash'] = self.hash_block(block)

hash_block函数如下:

@staticmethod
def hash_block(block):

    block_string = json.dumps(block, sort_keys=True)
    return hash(block_string)

该函数创建的哈希值与下一个区块所述的哈希值不同(前面的区块的哈希值与前面块的previous_hash不匹配)。然而,它们使用相同的函数:
这行代码: 'previous_hash': previous_hash or self.hash_block(self.chain[-1]) 和这行代码: block['hash'] = self.hash_block(block) 是重要的行(以及hash_block函数)。创建一个块,对其进行哈希计算并附加哈希值,然后创建另一个块并对上一个块进行哈希计算,但是当创建该块时,所生成的哈希值与该块的哈希值不匹配。
另外,我最初使用了hashlib.sha256,当我注意到这个问题后,我决定看看是否是哈希函数的问题,所以我切换到了stock哈希,但我仍然遇到了这个问题 - 最终我想让它在hashlib上工作,但我认为如果我能先让它在hash上工作...我就解决了在hashlib上的问题。

我注意到您没有包括输入、期望的输出和实际输出,即使是虚构的数据。我无法帮助您解决您的散列问题,因为您并没有给出一个体面的 [MCVE]。 - Martijn Pieters
3个回答

6

hash()函数仅适用于生成映射、哈希表。它使用一个随机种子来防止攻击。它不是加密哈希,不能保证在Python调用之间稳定。

hash()函数文档中可以了解到:

返回对象的哈希值(如果有)。哈希值是整数。它们用于在字典查找期间快速比较字典键。相等的数字值具有相同的哈希值(即使它们是不同类型的,例如1和1.0)。

以及从__hash__钩子方法中可以了解到,如果存在,hash()会调用该方法:

注意:默认情况下,字符串、字节和日期时间对象的__hash__()值会与不可预测的随机值“混淆”。虽然它们在单个Python进程中保持不变,但它们在重复调用Python时不可预测。

请使用hashlib模块选项,因为它们在调用之间是稳定的。

除此之外,在单个Python进程中,具有相同值的对象上的hash()也将产生完全相同的哈希值。由于您的block字典在块之间发生变化(因为它包括链中前一个块的哈希),因此它自然不是相同的字符串,因此哈希值也不同。

hashlib函数也是如此;它们仅对相同输入产生相同的值。如果哈希值不同,则输入不同。而您的输入自然不同,因为每个block字典都包括对前一个哈希的引用。


很酷没问题 - 哈希算法 hashlib.sha256 也遇到了同样的问题。 - ewizard
除此之外...这些不是重复的调用...哈希似乎在不同的位置创建相同...除了它最初哈希块的位置。 - ewizard
@ewizard:在同一个 Python 解释器中(不重新启动),字符串的 hash() 值(例如由 json.dumps() 返回的值)仅当值完全相同时才相同。如果它们不相同,则字符串不相同。 - Martijn Pieters
啊,好的,可能就是这样!我会尝试想出一个解决方案。 - ewizard

2

根据Martijn Pieters的回答,Python的hash()函数使用随机种子生成哈希值。而hashlib函数是确定性的,因此为了每次获得相同的哈希值,可以使用以下方法:

import hashlib
def get_hash(string:str):
    return hashlib.sha256(string.encode("utf-8")).hexdigest()

这可以用作:

some_hash_code=get_hash("One sentence")
print(some_hash_code)

输出结果为:

9d8c9567f9bfd8112d43c14e3e394ae97599afe39b6d7ef66cf365e342f009d4

每次


0

在打印将要进行json.dumps的对象后,我注意到它保留了添加的hash属性(我以为它没有)- 检查您的变量


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接