如何在Python中对原始二进制位字符串计算SHA256哈希值?
问题:如何对二进制字符串对应的原始二进制位计算SHA256哈希?
我有一个表示二进制数据的字符串:
h = '''0011001010000101011111010000101111111111101000001001000001001010110100010101111001001011000100111100011110001001111011110111011010010100110011001110111001100010111011010010101101010011110100100110101111110001100101011001000110100010000110110001100101110001'''
我原本写了这段代码计算SHA256:
a = binascii.hexlify(hashlib.sha256(bytes(h,'utf-8')).digest()).decode()
得到的结果是:
44f6dafa3d7a1720b5ebbf2adc1663df4dab03776eed48d2cda775237a547e59
但后来我意识到,这段代码计算的是字符串ASCII编码的SHA256哈希,而我实际需要的是把这个字符串当成原始二进制位序列来计算SHA256,就像执行这条Shell命令的效果:
$ echo 0011001010000101011111010000101111111111101000001001000001001010110100010101111001001011000100111100011110001001111011110111011010010100110011001110111001100010111011010010101101010011110100100110101111110001100101011001000110100010000110110001100101110001 | shasum -a 256 -0
这个命令给出的目标哈希值是:
f3f06d74b794b20645460aa0b17d4e7a77eaaea283ee55344adbfcece4a63432
我试了很多方法都出错了,请问该怎么实现这个需求?
解决方案
问题出在你原来的代码处理方式:bytes(h, 'utf-8')会把字符串里的每个'0'和'1'转换成对应的ASCII字节('0'→0x30,'1'→0x31),相当于哈希了这些ASCII字符组成的字节流,而不是把二进制字符串解析成原始的二进制数据。
要实现和shasum -a 256 -0相同的效果,你需要先把二进制字符串转换成对应的原始字节序列,再计算哈希。具体步骤如下:
完整Python代码
import hashlib import binascii h = '''0011001010000101011111010000101111111111101000001001000001001010110100010101111001001011000100111100011110001001111011110111011010010100110011001110111001100010111011010010101101010011110100100110101111110001100101011001000110100010000110110001100101110001''' # 1. 将二进制字符串转换为整数(base=2表示二进制) binary_integer = int(h, 2) # 2. 计算所需的字节数(如果字符串长度不是8的倍数,向上取整) byte_count = (len(h) + 7) // 8 # 3. 将整数转换为字节序列,使用大端字节序(对应从左到右的位顺序) raw_binary_bytes = binary_integer.to_bytes(byte_count, byteorder='big') # 4. 计算SHA256哈希并转为十六进制字符串 target_hash = binascii.hexlify(hashlib.sha256(raw_binary_bytes).digest()).decode() print(target_hash)
运行这段代码后,你会得到目标哈希值:
f3f06d74b794b20645460aa0b17d4e7a77eaaea283ee55344adbfcece4a63432
代码解释
int(h, 2):把整个二进制字符串解析成一个十进制整数,这一步会自动处理所有的0和1位。(len(h) +7)//8:计算需要多少个字节来存储这些二进制位。比如如果字符串长度是25位,(25+7)//8=4,也就是需要4个字节(32位),不足的位会在字节的高位补零(符合shasum -0的处理逻辑)。to_bytes(..., byteorder='big'):把整数转换成字节序列,大端字节序保证了二进制字符串最左边的位对应字节序列中第一个字节的最高位,和Shell命令的处理方式完全一致。- 最后计算SHA256哈希并转换成十六进制字符串,就得到了你想要的结果。
内容的提问来源于stack exchange,提问作者Alfie Stoppani
相关产品推荐
相关产品推荐

