所以我想了解 hashlib.md5 是如何工作的并生成了以下代码:
import hashlib
a = b'yolo'
h = hashlib.md5(a).digest()
b = h[6:10]
print(h)
print(b)
不要介意我使用“yolo”作为字符串。这只是为了测试。
现在运行此代码时,它会产生
b'O\xde\xd1FG6\xe7xe\xdf#,\xbc\xb4\xcd\x19'
b'\xe7xe\xdf'
坦率地说,这似乎不对。首先,我预计第二行会出现 4 个字节(包括字节 6-9),而第一部分 (the
\xe7xe
) 甚至不是一个字节 (afaik)。
文档说我应该从对
digest()
的调用中获取一个字节对象,但由于某种原因,情况似乎并非如此(?..)。我的理解是,一个 bytes 对象只是一个字节列表(因此该函数应该产生像 b'\x0f\xff\x75...'
或其他什么的输出,并且永远不会产生包含 \xe7xe
或以字母开头的输出)。我在这里误解了什么?
b'\xe7xe\xdf'
是一个 bytes
,恰好有四个字节:
>>> [hex(b) for b in b'\xe7xe\xdf']
['0xe7', '0x78', '0x65', '0xdf']
恰好其中两个字节落在 ASCII 可打印范围内,因此它们被表示为字符而不是
\x##
序列。
0x78
是 x
0x65
是 e
为了确认,您可以将
b'\xe7\x78\x65\xdf'
与 b'\xe7xe\xdf'
进行比较。它们是完全相同字节的两种不同表示:
>>> b'\xe7\x78\x65\xdf' == b'\xe7xe\xdf'
True
.hexdigest()
这将为您提供字符串
import hashlib
h = hashlib.md5(b'yolo').hexdigest()
print(h) # 4fded1464736e77865df232cbcb4cd19
请记住,现在每个字节都使用 2 个字符表示,因此例如要获取前 3 个字节,您应该这样做
print(h[:6]) # 4fded1
代码中的问题是在
digest()
模块中使用 hashlib
方法。 digest()
方法将哈希值作为字节对象返回,不适合直接切片和提取特定字节。
要获得所需的行为,您可以使用 hexdigest()
方法,该方法以十六进制数字字符串形式返回哈希值。然后,您可以对该字符串进行切片以提取所需的字节。
import hashlib
a = b'yolo'
h = hashlib.md5(a).hexdigest()
b = bytes.fromhex(h[12:20])
print(h)
print(b)
输出:
364fddd1464736e7xedf23cbcdb4cd19
b'\xe7\xed\xf2\x3c\xbc\xdb\x4