hashlib - 安全哈希和消息摘要

源代码: Lib/hashlib.py


此模块为许多不同的安全哈希和消息摘要算法实现了通用接口。其中包括 FIPS 安全哈希算法 SHA1、SHA224、SHA256、SHA384、SHA512(定义于 FIPS 180-4 标准)、SHA-3 系列(定义于 FIPS 202 标准)以及 RSA 的 MD5 算法(定义于互联网 RFC 1321)。“安全哈希”和“消息摘要”这两个术语可以互换使用。较旧的算法被称为消息摘要。现代术语是安全哈希。

注意

如果您需要 adler32 或 crc32 哈希函数,它们在 zlib 模块中可用。

哈希算法

每个 哈希 类型都有一个以其命名的构造函数方法。所有方法都返回一个具有相同简单接口的哈希对象。例如:使用 sha256() 创建一个 SHA-256 哈希对象。您现在可以使用 类字节对象(通常是 bytes)通过 update 方法向此对象提供数据。您可以随时使用 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-seealso 部分。

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 现在将使用它们。

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)

这是一个通用构造函数,它将所需算法的字符串 *name* 作为其第一个参数。 它也用于允许访问上面列出的哈希以及您的 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

一个集合,其中包含保证在所有平台上都受此模块支持的哈希算法的名称。 请注意,尽管某些上游供应商提供了一个奇怪的“符合 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() 算法提供可变长度摘要,其长度(以比特为单位)//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 对象以及类似对象。该函数可能会绕过 Python 的 I/O 并直接使用 fileno() 中的文件描述符。在此函数返回或引发异常后,应假定 *fileobj* 处于未知状态。关闭 *fileobj* 是调用者的责任。

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

示例

>>> import io, hashlib, hmac
>>> with open(hashlib.__file__, "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 版新增。

密钥派生

密钥派生和密钥扩展算法专为安全的密码哈希而设计。诸如 sha1(password) 之类的简单算法无法抵抗暴力攻击。良好的密码哈希函数必须是可调的、缓慢的,并且包含

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'

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

3.4 版新增。

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

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

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

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

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

3.6 版新增。

BLAKE2

BLAKE2RFC 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,或顺序模式为 0)。

  • node_depth:节点深度(0 到 255,叶子为 0,或顺序模式为 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 字节。例如,要将 SHA-1 替换为 BLAKE2b 而不更改输出大小,我们可以告诉 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 中,salt 在初始化期间作为哈希函数的一次性输入进行处理,而不是作为每个压缩函数的输入。

警告

使用 BLAKE2 或任何其他通用加密哈希函数(例如 SHA-256)进行*加盐哈希*(或仅哈希)不适合哈希密码。有关更多信息,请参阅BLAKE2 常见问题解答

>>> 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 页)

可以通过将字节传递给*person*参数来对 BLAKE2 进行个性化。

>>> 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/publications/detail/fips/202/final

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

https://www.blake2.net/

BLAKE2 官方网站。

https://zh.wikipedia.org/wiki/%E5%AF%86%E7%A0%81%E6%95%A3%E5%88%97%E5%87%BD%E6%95%B0

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

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

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

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

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