hashlib — 安全哈希与消息摘要

源代码: Lib/hashlib.py


此模块为多种不同的哈希算法实现了一个通用的接口。其中包括 FIPS 安全哈希算法 SHA224、SHA256、SHA384、SHA512(定义于 FIPS 180-4 标准)、SHA-3 系列(定义于 FIPS 202 标准),以及旧有算法 SHA1(曾是 FIPS 的一部分)和 MD5 算法(定义于互联网 RFC 1321)。

备注

如果你想要 adler32 或 crc32 哈希函数,它们在 zlib 模块中提供。

哈希算法

每种*哈希*类型都有一个同名的构造方法。所有构造方法都返回一个具有相同简单接口的哈希对象。例如:使用 sha256() 创建一个 SHA-256 哈希对象。你现在可以使用 update 方法向这个对象提供 类字节对象(通常是 bytes)。在任何时候,你都可以使用 digest()hexdigest() 方法,请求获取到目前为止提供给它的数据的拼接结果的*摘要*。

为了支持多线程,当在其构造函数或 .update 方法中一次性提供了超过 2047 字节的数据来计算哈希时,Python 的 GIL 会被释放。

此模块中始终存在的哈希算法构造函数有 sha1()sha224()sha256()sha384()sha512()sha3_224()sha3_256()sha3_384()sha3_512()shake_128()shake_256()blake2b()blake2s()md5() 通常也可用,但如果你使用的是罕见的“FIPS 兼容”版 Python,它可能会缺失或被禁用。这些算法对应于 algorithms_guaranteed

如果你的 Python 发行版的 hashlib 链接了一个提供了其他算法的 OpenSSL 构建版本,那么可能还会有其他算法可用。其他算法*不保证*在所有安装中都可用,并且只能通过 new() 按名称访问。请参阅 algorithms_available

警告

某些算法存在已知的哈希碰撞弱点(包括 MD5 和 SHA1)。请参阅针对加密哈希算法的攻击以及本文档末尾的 hashlib-另请参阅部分。

在 3.6 版本加入: 添加了 SHA3 (Keccak) 和 SHAKE 构造函数 sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256()。 添加了 blake2b()blake2s()

在 3.9 版更改: 所有的 hashlib 构造函数都接受一个仅限关键字的参数 usedforsecurity,默认值为 True。一个 false 值允许在受限环境中使用不安全和被禁用的哈希算法。False 表示该哈希算法不用于安全上下文,例如作为非加密的单向压缩函数。

在 3.9 版更改: 如果 OpenSSL 提供了 SHA3 和 SHAKE,hashlib 现在会使用 OpenSSL 的实现。

在 3.12 版更改: 对于链接的 OpenSSL 不提供的任何 MD5、SHA1、SHA2 或 SHA3 算法,我们将回退到 HACL* 项目提供的经过验证的实现。

用法

要获取字节字符串 b"Nobody inspects the spammish repetition" 的摘要

>>> import hashlib
>>> m = hashlib.sha256()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
>>> m.digest()
b'\x03\x1e\xdd}Ae\x15\x93\xc5\xfe\\\x00o\xa5u+7\xfd\xdf\xf7\xbcN\x84:\xa6\xaf\x0c\x95\x0fK\x94\x06'
>>> m.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'

更简洁的方式

>>> hashlib.sha256(b"Nobody inspects the spammish repetition").hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'

构造函数

hashlib.new(name, [data, ]*, usedforsecurity=True)

这是一个通用构造函数,它接受所需算法的字符串*名称*作为其第一个参数。它还用于访问上面列出的哈希算法以及你的 OpenSSL 库可能提供的任何其他算法。

使用 new() 配合算法名称

>>> h = hashlib.new('sha256')
>>> h.update(b"Nobody inspects the spammish repetition")
>>> h.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'
hashlib.md5([data, ]*, usedforsecurity=True)
hashlib.sha1([data, ]*, usedforsecurity=True)
hashlib.sha224([data, ]*, usedforsecurity=True)
hashlib.sha256([data, ]*, usedforsecurity=True)
hashlib.sha384([data, ]*, usedforsecurity=True)
hashlib.sha512([data, ]*, usedforsecurity=True)
hashlib.sha3_224([data, ]*, usedforsecurity=True)
hashlib.sha3_256([data, ]*, usedforsecurity=True)
hashlib.sha3_384([data, ]*, usedforsecurity=True)
hashlib.sha3_512([data, ]*, usedforsecurity=True)

像这样的具名构造函数比将算法名称传递给 new() 更快。

属性

Hashlib 提供了以下常量模块属性

hashlib.algorithms_guaranteed

一个集合,包含保证在此模块在所有平台上都支持的哈希算法名称。请注意,'md5' 也在这个列表中,尽管一些上游供应商提供了奇怪的“FIPS 兼容”Python 构建版本,该版本排除了 md5。

在 3.2 版本加入。

hashlib.algorithms_available

一个集合,包含在运行的 Python 解释器中可用的哈希算法名称。这些名称在传递给 new() 时将被识别。algorithms_guaranteed 将始终是它的一个子集。由于 OpenSSL 的原因,相同的算法可能会在此集合中以不同的名称出现多次。

在 3.2 版本加入。

哈希对象

构造函数返回的哈希对象提供了以下常量属性

hash.digest_size

结果哈希的字节大小。

hash.block_size

哈希算法的内部块大小(以字节为单位)。

一个哈希对象有以下属性

hash.name

此哈希算法的规范名称,始终为小写,并且始终适合作为 new() 的参数来创建另一个此类型的哈希。

在 3.4 版更改: name 属性自 CPython 诞生以来就存在,但直到 Python 3.4 才被正式指定,因此在某些平台上可能不存在。

一个哈希对象有以下方法

hash.update(data)

类字节对象更新哈希对象。重复调用等同于使用所有参数的拼接结果进行单次调用:m.update(a); m.update(b) 等同于 m.update(a+b)

hash.digest()

返回到目前为止传递给 update() 方法的数据的摘要。这是一个大小为 digest_size 的字节对象,可能包含 0 到 255 范围内的所有字节。

hash.hexdigest()

digest() 类似,但摘要以两倍长度的字符串对象形式返回,只包含十六进制数字。这可用于在电子邮件或其他非二进制环境中安全地交换值。

hash.copy()

返回哈希对象的副本(“克隆”)。这可以用来高效地计算共享相同初始子字符串的数据的摘要。

SHAKE 可变长度摘要

hashlib.shake_128([data, ]*, usedforsecurity=True)
hashlib.shake_256([data, ]*, usedforsecurity=True)

shake_128()shake_256() 算法提供可变长度的摘要,其安全级别为 length_in_bits//2,最高可达 128 或 256 位。因此,它们的摘要方法需要一个长度参数。最大长度不受 SHAKE 算法的限制。

shake.digest(length)

返回到目前为止传递给 update() 方法的数据的摘要。这是一个大小为 *length* 的字节对象,可能包含 0 到 255 范围内的所有字节。

shake.hexdigest(length)

digest() 类似,但摘要以两倍长度的字符串对象形式返回,只包含十六进制数字。这可用于在电子邮件或其他非二进制环境中安全地交换值。

使用示例

>>> h = hashlib.shake_256(b'Nobody inspects the spammish repetition')
>>> h.hexdigest(20)
'44709d6fcb83d92a76dcb0b668c98e1b1d3dafe7'

文件哈希

hashlib 模块提供了一个辅助函数,用于高效地对文件或类文件对象进行哈希计算。

hashlib.file_digest(fileobj, digest, /)

返回一个已用文件对象内容更新过的摘要对象。

fileobj 必须是一个以二进制模式打开用于读取的类文件对象。它接受来自内置 open() 的文件对象、BytesIO 实例、来自 socket.socket.makefile() 的 SocketIO 对象等类似对象。fileobj 必须以阻塞模式打开,否则可能会引发 BlockingIOError

该函数可能会绕过 Python 的 I/O,直接使用来自 fileno() 的文件描述符。在此函数返回或引发异常后,应假定 fileobj 处于未知状态。关闭 fileobj 是调用者的责任。

digest 必须是哈希算法名称的 *str*、哈希构造函数,或返回哈希对象的可调用对象。

示例

>>> import io, hashlib, hmac
>>> with open("library/hashlib.rst", "rb") as f:
...     digest = hashlib.file_digest(f, "sha256")
...
>>> digest.hexdigest()
'...'
>>> buf = io.BytesIO(b"somedata")
>>> mac1 = hmac.HMAC(b"key", digestmod=hashlib.sha512)
>>> digest = hashlib.file_digest(buf, lambda: mac1)
>>> digest is mac1
True
>>> mac2 = hmac.HMAC(b"key", b"somedata", digestmod=hashlib.sha512)
>>> mac1.digest() == mac2.digest()
True

在 3.11 版本中新增。

在 3.14 版更改: 现在如果文件以非阻塞模式打开,会引发 BlockingIOError。以前,摘要中会添加虚假的空字节。

密钥派生

密钥派生和密钥拉伸算法专为安全密码哈希而设计。像 sha1(password) 这样的朴素算法无法抵抗暴力破解攻击。一个好的密码哈希函数必须是可调的、缓慢的,并且包含一个盐(salt)

hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None)

该函数提供 PKCS#5 基于密码的密钥派生函数 2。它使用 HMAC 作为伪随机函数。

字符串 *hash_name* 是 HMAC 所需的哈希摘要算法的名称,例如 'sha1' 或 'sha256'。*password* 和 *salt* 被解释为字节缓冲区。应用程序和库应将 *password* 限制在一个合理的长度(例如 1024)。*salt* 应该来自一个合适的来源,大约 16 字节或更多,例如 os.urandom()

应根据哈希算法和计算能力选择 *iterations* 的数量。截至 2022 年,建议进行数十万次 SHA-256 迭代。关于为何以及如何为你的应用程序选择最佳迭代次数的理由,请阅读 NIST-SP-800-132 的 *附录 A.2.2*。stackexchange 上关于 pbkdf2 迭代次数问题的答案详细解释了这一点。

*dklen* 是派生密钥的字节长度。如果 *dklen* 为 None,则使用哈希算法 *hash_name* 的摘要大小,例如 SHA-512 为 64。

>>> from hashlib import pbkdf2_hmac
>>> our_app_iters = 500_000  # Application specific, read above.
>>> dk = pbkdf2_hmac('sha256', b'password', b'bad salt' * 2, our_app_iters)
>>> dk.hex()
'15530bba69924174860db778f2c6f8104d3aaf9d26241840c8c4a641c8d000a9'

此函数仅在 Python 使用 OpenSSL 编译时可用。

在 3.4 版本加入。

在 3.12 版更改: 该函数现在仅在 Python 使用 OpenSSL 构建时可用。缓慢的纯 Python 实现已被移除。

hashlib.scrypt(password, *, salt, n, r, p, maxmem=0, dklen=64)

该函数提供了 RFC 7914 中定义的 scrypt 基于密码的密钥派生函数。

passwordsalt 必须是 类字节对象。应用程序和库应将 password 限制在一个合理的长度(例如 1024)。salt 应该来自一个合适的来源,大约 16 字节或更多,例如 os.urandom()

n 是 CPU/内存成本因子,r 是块大小,p 是并行化因子,maxmem 限制内存(OpenSSL 1.1.0 默认为 32 MiB)。dklen 是派生密钥的字节长度。

在 3.6 版本加入。

BLAKE2

BLAKE2 是一个在 RFC 7693 中定义的加密哈希函数,它有两种形式

  • BLAKE2b,为 64 位平台优化,并产生 1 到 64 字节之间的任意大小的摘要,

  • BLAKE2s,为 8 到 32 位平台优化,并产生 1 到 32 字节之间的任意大小的摘要。

BLAKE2 支持 密钥模式(一种更快、更简单的 HMAC 替代品)、加盐哈希个性化树哈希

此模块中的哈希对象遵循标准库 hashlib 对象的 API。

创建哈希对象

通过调用构造函数创建新的哈希对象

hashlib.blake2b(data=b'', *, digest_size=64, key=b'', salt=b'', person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, inner_size=0, last_node=False, usedforsecurity=True)
hashlib.blake2s(data=b'', *, digest_size=32, key=b'', salt=b'', person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, inner_size=0, last_node=False, usedforsecurity=True)

这些函数返回相应的哈希对象,用于计算 BLAKE2b 或 BLAKE2s。它们可选地接受以下通用参数

  • data:要哈希的初始数据块,必须是类字节对象。它只能作为位置参数传递。

  • digest_size:输出摘要的字节大小。

  • key:用于密钥哈希的密钥(BLAKE2b 最多 64 字节,BLAKE2s 最多 32 字节)。

  • salt:用于随机化哈希的盐(BLAKE2b 最多 16 字节,BLAKE2s 最多 8 字节)。

  • person:个性化字符串(BLAKE2b 最多 16 字节,BLAKE2s 最多 8 字节)。

下表显示了通用参数的限制(以字节为单位)

哈希

digest_size

len(key)

len(salt)

len(person)

BLAKE2b

64

64

16

16

BLAKE2s

32

32

8

8

备注

BLAKE2 规范定义了盐和个性化参数的恒定长度,但是,为了方便起见,此实现接受任何大小不超过指定长度的字节字符串。如果参数的长度小于指定长度,它将被零填充,因此,例如,b'salt'b'salt\x00' 是相同的值。(对于 *key* 则不是这种情况。)

这些大小作为下面描述的模块 常量 提供。

构造函数还接受以下树哈希参数

  • fanout:扇出(0 到 255,如果无限则为 0,顺序模式下为 1)。

  • depth:树的最大深度(1 到 255,如果无限则为 255,顺序模式下为 1)。

  • leaf_size:叶的最大字节长度(0 到 2**32-1,如果无限或在顺序模式下为 0)。

  • node_offset:节点偏移量(对于 BLAKE2b 为 0 到 2**64-1,对于 BLAKE2s 为 0 到 2**48-1,对于第一个、最左边的叶子或在顺序模式下为 0)。

  • node_depth:节点深度(0 到 255,对于叶子或在顺序模式下为 0)。

  • inner_size:内部摘要大小(对于 BLAKE2b 为 0 到 64,对于 BLAKE2s 为 0 到 32,顺序模式下为 0)。

  • last_node:布尔值,指示处理的节点是否为最后一个(顺序模式下为 False)。

Explanation of tree mode parameters.

有关树哈希的全面回顾,请参阅 BLAKE2 规范的第 2.10 节。

常量

blake2b.SALT_SIZE
blake2s.SALT_SIZE

盐长度(构造函数接受的最大长度)。

blake2b.PERSON_SIZE
blake2s.PERSON_SIZE

个性化字符串长度(构造函数接受的最大长度)。

blake2b.MAX_KEY_SIZE
blake2s.MAX_KEY_SIZE

最大密钥大小。

blake2b.MAX_DIGEST_SIZE
blake2s.MAX_DIGEST_SIZE

哈希函数可以输出的最大摘要大小。

示例

简单哈希

要计算某些数据的哈希,您应该首先通过调用适当的构造函数(blake2b()blake2s())来构造一个哈希对象,然后通过在该对象上调用 update() 来更新数据,最后通过调用 digest()(或 hexdigest() 以获取十六进制编码的字符串)来从对象中获取摘要。

>>> from hashlib import blake2b
>>> h = blake2b()
>>> h.update(b'Hello world')
>>> h.hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'

作为快捷方式,您可以将要更新的第一块数据直接作为位置参数传递给构造函数

>>> from hashlib import blake2b
>>> blake2b(b'Hello world').hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'

您可以根据需要多次调用 hash.update() 来迭代更新哈希

>>> from hashlib import blake2b
>>> items = [b'Hello', b' ', b'world']
>>> h = blake2b()
>>> for item in items:
...     h.update(item)
...
>>> h.hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'

使用不同的摘要大小

BLAKE2 的摘要大小可配置,BLAKE2b 最多 64 字节,BLAKE2s 最多 32 字节。例如,要用 BLAKE2b 替换 SHA-1 而不改变输出大小,我们可以告诉 BLAKE2b 生成 20 字节的摘要

>>> from hashlib import blake2b
>>> h = blake2b(digest_size=20)
>>> h.update(b'Replacing SHA1 with the more secure function')
>>> h.hexdigest()
'd24f26cf8de66472d58d4e1b1774b4c9158b1f4c'
>>> h.digest_size
20
>>> len(h.digest())
20

具有不同摘要大小的哈希对象有完全不同的输出(较短的哈希*不是*较长哈希的前缀);即使输出长度相同,BLAKE2b 和 BLAKE2s 也会产生不同的输出

>>> from hashlib import blake2b, blake2s
>>> blake2b(digest_size=10).hexdigest()
'6fa1d8fcfd719046d762'
>>> blake2b(digest_size=11).hexdigest()
'eb6ec15daf9546254f0809'
>>> blake2s(digest_size=10).hexdigest()
'1bf21a98c78a1c376ae9'
>>> blake2s(digest_size=11).hexdigest()
'567004bf96e4a25773ebf4'

密钥哈希

密钥哈希可用于身份验证,作为 基于哈希的消息认证码 (HMAC) 的更快、更简单的替代方案。由于继承自 BLAKE 的不可区分性属性,BLAKE2 可以在前缀-MAC 模式下安全使用。

此示例展示了如何使用密钥 b'pseudorandom key' 为消息 b'message data' 获取一个(十六进制编码的)128 位认证码

>>> from hashlib import blake2b
>>> h = blake2b(key=b'pseudorandom key', digest_size=16)
>>> h.update(b'message data')
>>> h.hexdigest()
'3d363ff7401e02026f4a4687d4863ced'

作为一个实际的例子,一个 Web 应用程序可以对称地对发送给用户的 cookie 进行签名,并在之后验证它们,以确保它们没有被篡改

>>> from hashlib import blake2b
>>> from hmac import compare_digest
>>>
>>> SECRET_KEY = b'pseudorandomly generated server secret key'
>>> AUTH_SIZE = 16
>>>
>>> def sign(cookie):
...     h = blake2b(digest_size=AUTH_SIZE, key=SECRET_KEY)
...     h.update(cookie)
...     return h.hexdigest().encode('utf-8')
>>>
>>> def verify(cookie, sig):
...     good_sig = sign(cookie)
...     return compare_digest(good_sig, sig)
>>>
>>> cookie = b'user-alice'
>>> sig = sign(cookie)
>>> print("{0},{1}".format(cookie.decode('utf-8'), sig))
user-alice,b'43b3c982cf697e0c5ab22172d1ca7421'
>>> verify(cookie, sig)
True
>>> verify(b'user-bob', sig)
False
>>> verify(cookie, b'0102030405060708090a0b0c0d0e0f00')
False

尽管有原生的密钥哈希模式,BLAKE2 当然也可以与 hmac 模块一起用于 HMAC 构造中

>>> import hmac, hashlib
>>> m = hmac.new(b'secret key', digestmod=hashlib.blake2s)
>>> m.update(b'message')
>>> m.hexdigest()
'e3c8102868d28b5ff85fc35dda07329970d1a01e273c37481326fe0c861c8142'

随机化哈希

通过设置 *salt* 参数,用户可以向哈希函数引入随机性。随机化哈希对于防止数字签名中使用的哈希函数受到碰撞攻击非常有用。

随机化哈希是为这样一种情况设计的:一方(消息准备者)生成要由第二方(消息签名者)签名的消息的全部或部分。如果消息准备者能够找到加密哈希函数的碰撞(即,两条消息产生相同的哈希值),那么他们可能会准备出产生相同哈希值和数字签名但结果不同的有意义的消息版本(例如,向一个账户转账 $1,000,000,而不是 $10)。加密哈希函数的设计以抗碰撞性为主要目标,但目前对攻击加密哈希函数的关注可能会导致某个给定的加密哈希函数提供的抗碰撞性低于预期。随机化哈希通过降低准备者在数字签名生成过程中生成两条或更多最终产生相同哈希值的消息的可能性,为签名者提供了额外的保护——即使找到该哈希函数的碰撞是可行的。然而,当消息的所有部分都由签名者准备时,使用随机化哈希可能会降低数字签名提供的安全性。

NIST SP-800-106 “数字签名的随机化哈希”

在 BLAKE2 中,盐是在初始化期间作为哈希函数的一次性输入进行处理的,而不是作为每个压缩函数的输入。

警告

使用 BLAKE2 或任何其他通用加密哈希函数(如 SHA-256)进行*加盐哈希*(或简称哈希)不适合用于哈希密码。更多信息请参阅 BLAKE2 FAQ

>>> import os
>>> from hashlib import blake2b
>>> msg = b'some message'
>>> # Calculate the first hash with a random salt.
>>> salt1 = os.urandom(blake2b.SALT_SIZE)
>>> h1 = blake2b(salt=salt1)
>>> h1.update(msg)
>>> # Calculate the second hash with a different random salt.
>>> salt2 = os.urandom(blake2b.SALT_SIZE)
>>> h2 = blake2b(salt=salt2)
>>> h2.update(msg)
>>> # The digests are different.
>>> h1.digest() != h2.digest()
True

个性化

有时,为了不同的目的,强制哈希函数对相同的输入产生不同的摘要是很有用的。引用 Skein 哈希函数的作者的话

我们建议所有应用程序设计者认真考虑这样做;我们见过很多协议,其中在协议的一个部分计算的哈希可以在一个完全不同的部分使用,因为两个哈希计算是在相似或相关的数据上进行的,攻击者可以强制应用程序使哈希输入相同。对协议中使用的每个哈希函数进行个性化可以立即阻止这类攻击。

Skein 哈希函数家族,第 21 页)

BLAKE2 可以通过向 *person* 参数传递字节来进行个性化

>>> from hashlib import blake2b
>>> FILES_HASH_PERSON = b'MyApp Files Hash'
>>> BLOCK_HASH_PERSON = b'MyApp Block Hash'
>>> h = blake2b(digest_size=32, person=FILES_HASH_PERSON)
>>> h.update(b'the same content')
>>> h.hexdigest()
'20d9cd024d4fb086aae819a1432dd2466de12947831b75c5a30cf2676095d3b4'
>>> h = blake2b(digest_size=32, person=BLOCK_HASH_PERSON)
>>> h.update(b'the same content')
>>> h.hexdigest()
'cf68fb5761b9c44e7878bfb2c4c9aea52264a80b75005e65619778de59f383a3'

个性化与密钥模式一起也可以用于从单个密钥派生出不同的密钥。

>>> from hashlib import blake2s
>>> from base64 import b64decode, b64encode
>>> orig_key = b64decode(b'Rm5EPJai72qcK3RGBpW3vPNfZy5OZothY+kHY6h21KM=')
>>> enc_key = blake2s(key=orig_key, person=b'kEncrypt').digest()
>>> mac_key = blake2s(key=orig_key, person=b'kMAC').digest()
>>> print(b64encode(enc_key).decode('utf-8'))
rbPb15S/Z9t+agffno5wuhB77VbRi6F9Iv2qIxU7WHw=
>>> print(b64encode(mac_key).decode('utf-8'))
G9GtHFE1YluXY1zWPlYk1e/nWfu0WSEb0KRcjhDeP/o=

树模式

以下是一个哈希具有两个叶节点的最小树的示例

  10
 /  \
00  01

此示例使用 64 字节的内部摘要,并返回 32 字节的最终摘要

>>> from hashlib import blake2b
>>>
>>> FANOUT = 2
>>> DEPTH = 2
>>> LEAF_SIZE = 4096
>>> INNER_SIZE = 64
>>>
>>> buf = bytearray(6000)
>>>
>>> # Left leaf
... h00 = blake2b(buf[0:LEAF_SIZE], fanout=FANOUT, depth=DEPTH,
...               leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
...               node_offset=0, node_depth=0, last_node=False)
>>> # Right leaf
... h01 = blake2b(buf[LEAF_SIZE:], fanout=FANOUT, depth=DEPTH,
...               leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
...               node_offset=1, node_depth=0, last_node=True)
>>> # Root node
... h10 = blake2b(digest_size=32, fanout=FANOUT, depth=DEPTH,
...               leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
...               node_offset=0, node_depth=1, last_node=True)
>>> h10.update(h00.digest())
>>> h10.update(h01.digest())
>>> h10.hexdigest()
'3ad2a9b37c6070e374c7a8c508fe20ca86b6ed54e286e93a0318e95e881db5aa'

致谢

BLAKE2 由 *Jean-Philippe Aumasson*、*Samuel Neves*、*Zooko Wilcox-O'Hearn* 和 *Christian Winnerlein* 设计,基于由 *Jean-Philippe Aumasson*、*Luca Henzen*、*Willi Meier* 和 *Raphael C.-W. Phan* 创建的 SHA-3 决赛选手 BLAKE

它使用了由 *Daniel J. Bernstein* 设计的 ChaCha 密码的核心算法。

stdlib 实现基于 pyblake2 模块。它由 *Dmitry Chestnykh* 编写,基于 *Samuel Neves* 编写的 C 实现。文档从 pyblake2 复制而来,由 *Dmitry Chestnykh* 编写。

C 代码由 *Christian Heimes* 为 Python 部分重写。

以下公共领域贡献声明适用于 C 哈希函数实现、扩展代码和此文档

在法律允许的范围内,作者已将本软件的所有版权及相关和邻接权在全球范围内奉献给公共领域。本软件按原样分发,不附带任何保证。

您应该已经随本软件收到一份 CC0 公共领域贡献声明的副本。如果没有,请参阅 https://creativecommons.org/publicdomain/zero/1.0/

以下人员为项目开发提供了帮助或根据知识共享公共领域贡献声明 1.0 通用版贡献了他们的更改

  • Alexandr Sokolovskiy

参见

hmac 模块

一个使用哈希生成消息认证码的模块。

模块 base64

另一种在非二进制环境中编码二进制哈希的方法。

https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.180-4.pdf

关于安全哈希算法的 FIPS 180-4 出版物。

https://csrc.nist.gov/pubs/fips/202/final

关于 SHA-3 标准的 FIPS 202 出版物。

https://www.blake2.net/

BLAKE2 官方网站。

https://en.wikipedia.org/wiki/Cryptographic_hash_function

维基百科文章,包含有关哪些算法存在已知问题以及这对其使用意味着什么的信息。

https://www.ietf.org/rfc/rfc8018.txt

PKCS #5:基于密码的加密规范 2.1 版

https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf

NIST 对基于密码的密钥派生的建议。