在Python3中比较哈希位的最快方法是什么?

时间:2013-03-26 15:45:33

标签: python hash python-3.x binary hashlib

我希望比较Python3中的哈希位,作为Hashcash系统的一部分。 因此,例如,我想知道SHA256哈希的前N位是否为0。

现在,我正在基于十六进制版本

这样做
  if newhash.hexdigest()[0:4] == '0000'

但是这并不能让我像我想要的那样精细 - 我更愿意比较原始位,这让我可以更接近地改变匹配0的数量。

我通过复杂的跳

得到要比较的比特值
  bin(int(h.hexdigest(), 16))[2:]

但这似乎不太可能是最快/正确的方法。

我很感激任何关于正确/正确方法的建议;)

谢谢,

-CPD

3 个答案:

答案 0 :(得分:1)

要检查数字的选定位是否为零,您需要and使用预计算掩码的数字,并设置所有这些位,并将结果与​​零进行比较。检查n位数的前m位的掩码是由n 1s后跟m - n 0的二进制数组成的数字。

def mask(n, m):
    return ((1 << n) - 1) << (m - n)

def test_0bits(digest_bytes, n_bits):
    m = 8 * len(digest_bytes)
    digest_num = int.from_bytes(digest_bytes, 'big')
    return digest_num & mask(n_bits, m) == 0

>>> test_0bits(b'\123\456', 3)  # 001 010 011 100 101 110
False
>>> test_0bits(b'\023\456', 3)  # 000 010 011 100 101 110
True

如果您使用相同的位数调用test_bits,则可以预先计算掩码并将其存储为模块级“常量”。

答案 1 :(得分:0)

您可以像这样解压缩摘要的前8个字节:

bin(struct.unpack('>Q', h.digest()[:8])[0])

但是我不确定它是否更快,并且对其余部分来说不方便。在Python中,琐事并不容易。

答案 2 :(得分:0)

如果你可以处理右边的索引位,gmpy2中的整数类型支持切片来访问各个位:

>>> x=gmpy2.mpz(12345)
>>> x.digits(2)
'11000000111001'
>>> x[2:5].digits(2)
'110'

如果需要修改单个位,gmpy2包含一个可变整数类型,允许您修改位。

免责声明:我维持gmpy2。