我希望比较Python3中的哈希位,作为Hashcash系统的一部分。 因此,例如,我想知道SHA256哈希的前N位是否为0。
现在,我正在基于十六进制版本
这样做 if newhash.hexdigest()[0:4] == '0000'
但是这并不能让我像我想要的那样精细 - 我更愿意比较原始位,这让我可以更接近地改变匹配0的数量。
我通过复杂的跳
得到要比较的比特值 bin(int(h.hexdigest(), 16))[2:]
但这似乎不太可能是最快/正确的方法。
我很感激任何关于正确/正确方法的建议;)
谢谢,
-CPD
答案 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。