Содержание страницы
hashlib – безопасные хеши и дайджесты сообщений¶hashlib – Secure hashes and message digests
Исходный код: Lib/hashlib.py
This module implements a common interface to many different hash algorithms. Included are the FIPS secure hash algorithms SHA224, SHA256, SHA384, SHA512, (defined in the FIPS 180-4 standard), the SHA-3 series (defined in the FIPS 202 standard) as well as the legacy algorithms SHA1 (formerly part of FIPS) and the MD5 algorithm (defined in internet RFC 1321).
Примечание
Если вам нужны хеш-функции adler32 или crc32, они доступны в модуле zlib.
Алгоритмы хеширования¶Hash algorithms
There is one constructor method named for each type of hash. All return
a hash object with the same simple interface. For example: use sha256()
to create a SHA-256 hash object. You can now feed this object with
bytes-like objects (normally bytes) using
the update method. At any point you can ask it for the
digest of the concatenation of the data fed to it so far using the
digest() or hexdigest() methods.
To allow multithreading, the Python GIL is released while computing a
hash supplied more than 2047 bytes of data at once in its constructor or
.update method.
Конструкторы хеш-алгоритмов, которые всегда присутствуют в этом модуле: md5(), sha1(), sha224(), sha256(), sha384(), sha512(), sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256(), blake2b() и blake2s(). Они соответствуют algorithms_guaranteed.
Тем не менее любой из них может отсутствовать или быть заблокирован в необычных средах, например в редкой «FIPS-совместимой» сборке Python или когда «режим FIPS» OpenSSL настроен на исключение некоторых алгоритмов из поставщика по умолчанию. Вызов конструктора недоступного алгоритма вызывает ValueError.
Additional algorithms may also be available if your Python distribution’s
hashlib was linked against a build of OpenSSL that provides others.
Others are not guaranteed available on all installations and will only be
accessible by name via new(). See algorithms_available.
Предупреждение
Some algorithms have known hash collision weaknesses (including MD5 and SHA1). Refer to Attacks on cryptographic hash algorithms and the hashlib-seealso section at the end of this document.
Added in version 3.6: SHA3 (Keccak) and SHAKE constructors sha3_224(), sha3_256(),
sha3_384(), sha3_512(), shake_128(), shake_256()
were added.
blake2b() and blake2s() were added.
Changed in version 3.9: All hashlib constructors take a keyword-only argument usedforsecurity
with default value True. A false value allows the use of insecure and
blocked hashing algorithms in restricted environments. False indicates
that the hashing algorithm is not used in a security context, e.g. as a
non-cryptographic one-way compression function.
Changed in version 3.9: Hashlib now uses SHA3 and SHAKE from OpenSSL if it provides it.
Changed in version 3.12: For any of the MD5, SHA1, SHA2, or SHA3 algorithms that the linked OpenSSL does not provide we fall back to a verified implementation from the HACL* project.
Устарело с версии 3.15, будет удалено в версии 3.19: Недокументированный именованный параметр string в _hashlib.new() и конструкторах, названных по хешу, таких как _md5.md5(), устарел. Рекомендуется передавать начальные данные как позиционный аргумент для максимальной обратной совместимости.
Использование¶Usage
Чтобы получить дайджест байтовой строки 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'
Конструкторы¶Constructors
- hashlib.new(name, [data, ]*, usedforsecurity=True)¶
Is a generic constructor that takes the string name of the desired algorithm as its first parameter. It also exists to allow access to the above listed hashes as well as any other algorithms that your OpenSSL library may offer.
Использование 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().
Атрибуты¶Attributes
Модуль hashlib предоставляет следующие константные атрибуты:
- hashlib.algorithms_guaranteed¶
Множество, содержащее имена хеш-алгоритмов, которые гарантированно поддерживаются этим модулем на всех платформах. Обратите внимание, что «md5» присутствует в этом списке, несмотря на то, что некоторые вышестоящие поставщики предлагают странную сборку Python «с поддержкой FIPS», которая его исключает.
Добавлено в версии 3.2.
- hashlib.algorithms_available¶
Множество, содержащее имена хеш-алгоритмов, доступных в работающем интерпретаторе Python. Эти имена будут распознаны при передаче в
new().algorithms_guaranteedвсегда будет подмножеством. Один и тот же алгоритм может появляться в этом множестве несколько раз под разными именами (благодаря OpenSSL).Добавлено в версии 3.2.
Хеш-объекты¶Hash Objects
Следующие значения предоставляются в качестве константных атрибутов хеш-объектов, возвращаемых конструкторами:
- 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¶SHAKE variable length digests
- 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()на текущий момент. Это объект bytes размером length, который может содержать байты во всём диапазоне от 0 до 255.
- shake.hexdigest(length)¶
Как и
digest(), но дайджест возвращается в виде строкового объекта двойной длины, содержащего только шестнадцатеричные цифры. Это может использоваться для обмена значениями в электронной почте или других небинарных средах.
Пример использования:
>>> h = hashlib.shake_256(b'Nobody inspects the spammish repetition')
>>> h.hexdigest(20)
'44709d6fcb83d92a76dcb0b668c98e1b1d3dafe7'
Хэширование файлов¶File hashing
Модуль hashlib предоставляет вспомогательную функцию для эффективного хэширования файла или файлоподобного объекта.
- hashlib.file_digest(fileobj, digest, /)¶
Возвращает объект дайджеста, обновлённый содержимым файлового объекта.
fileobj должен быть файлоподобным объектом, открытым для чтения в двоичном режиме. Он принимает файловые объекты от встроенных
open(), экземпляровBytesIO, объектов SocketIO изsocket.socket.makefile()и т.п. fileobj должен быть открыт в блокирующем режиме, иначе может быть возбужденоBlockingIOError.Функция может обходить ввод-вывод Python и использовать файловый дескриптор из
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.12.
Изменено в версии 3.14: Теперь возбуждает
BlockingIOError, если файл открыт в неблокирующем режиме. Ранее в дайджест добавлялись ложные нулевые байты.
Вывод ключей¶Key derivation
Алгоритмы вывода ключей и растяжения ключей предназначены для безопасного хэширования паролей. Простые алгоритмы, такие как 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().Количество итераций следует выбирать на основе алгоритма хэширования и вычислительной мощности. По состоянию на 2022 год рекомендуются сотни тысяч итераций SHA-256. Обоснование того, почему и как выбрать оптимальное значение для вашего приложения, см. в Приложении A.2.2 к NIST-SP-800-132. Ответы на вопрос stackexchange об итерациях pbkdf2 подробно это объясняют.
dklen – это длина производного ключа в байтах. Если dklen равно
None, то используется размер дайджеста алгоритма хэширования hash_name, например 64 для SHA-512.>>> from hashlib import pbkdf2_hmac >>> our_app_iters = 500_000 # Зависит от приложения, см. выше. >>> 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)¶
Функция реализует функцию вывода ключей на основе пароля scrypt, как определено в RFC 7914.
password и salt должны быть байтоподобными объектами. Приложениям и библиотекам следует ограничивать password разумной длиной (например, 1024). salt должна содержать около 16 или более байтов из надёжного источника, например
os.urandom().n – это фактор стоимости CPU/памяти, r – размер блока, p – фактор параллелизации, а maxmem ограничивает память (по умолчанию 32 МиБ в OpenSSL 1.1.0). dklen – длина производного ключа в байтах.
Добавлено в версии 3.6.
BLAKE2¶
BLAKE2 – это криптографическая хэш-функция, определённая в RFC 7693, которая существует в двух вариантах:
BLAKE2b, оптимизированная для 64-битных платформ и создающая дайджесты любого размера от 1 до 64 байтов,
BLAKE2s, оптимизированная для 8- и 32-битных платформ и создающая дайджесты любого размера от 1 до 32 байтов.
BLAKE2 поддерживает ключевой режим (более быструю и простую замену HMAC), хэширование с солью, персонализацию и древовидное хэширование.
Хэш-объекты этого модуля следуют API объектов стандартной библиотеки hashlib.
Создание хеш-объектов¶Creating hash objects
Новые хеш-объекты создаются вызовом функций-конструкторов:
- 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: ключ для хеширования с ключом (до 64 байт для BLAKE2b, до 32 байт для BLAKE2s).
salt: соль для рандомизированного хеширования (до 16 байт для BLAKE2b, до 8 байт для BLAKE2s).
person: строка персонализации (до 16 байт для BLAKE2b, до 8 байт для BLAKE2s).
Следующая таблица показывает ограничения для общих параметров (в байтах):
Хеш |
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: fanout (от 0 до 255, 0 – если без ограничения, 1 в последовательном режиме).
depth: максимальная глубина дерева (от 1 до 255, 255 – если без ограничения, 1 в последовательном режиме).
leaf_size: максимальная длина листа в байтах (от 0 до
2**32-1, 0 – если без ограничения или в последовательном режиме).node_offset: смещение узла (от 0 до
2**64-1для BLAKE2b, от 0 до2**48-1для BLAKE2s, 0 для первого, самого левого листа или в последовательном режиме).node_depth: глубина узла (от 0 до 255, 0 для листьев или в последовательном режиме).
inner_size: размер внутреннего дайджеста (от 0 до 64 для BLAKE2b, от 0 до 32 для BLAKE2s, 0 в последовательном режиме).
last_node: логическое значение, указывающее, является ли обрабатываемый узел последним (
Falseдля последовательного режима).
См. раздел 2.10 в спецификации BLAKE2 для всестороннего обзора хеширования деревьев.
Константы¶Constants
- 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¶
Максимальный размер дайджеста, который может выдать хеш-функция.
Примеры¶Examples
Простое хеширование¶Simple hashing
Чтобы вычислить хеш некоторых данных, сначала необходимо создать объект хеша, вызвав соответствующую функцию-конструктор (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'
Использование разных размеров дайджеста¶Using different digest sizes
BLAKE2 имеет настраиваемый размер дайджестов: до 64 байт для BLAKE2b и до 32 байт для BLAKE2s. Например, чтобы заменить 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'
Хеширование с ключом¶Keyed hashing
Хеширование с ключом может использоваться для аутентификации как более быстрая и простая замена коду аутентификации сообщений на основе хеша (HMAC). BLAKE2 можно безопасно использовать в режиме prefix-MAC благодаря свойству неразличимости, унаследованному от BLAKE.
Этот пример показывает, как получить (в шестнадцатеричной кодировке) 128-битный код аутентификации для сообщения b'message data' с ключом b'pseudorandom key':
>>> from hashlib import blake2b
>>> h = blake2b(key=b'pseudorandom key', digest_size=16)
>>> h.update(b'message data')
>>> h.hexdigest()
'3d363ff7401e02026f4a4687d4863ced'
В качестве практического примера: веб-приложение может симметрично подписывать куки, отправляемые пользователям, и впоследствии проверять их, чтобы убедиться, что они не были изменены:
>>> 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'
Рандомизированное хеширование¶Randomized hashing
Устанавливая параметр 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'
>>> # Вычислить первый хеш со случайной солью.
>>> salt1 = os.urandom(blake2b.SALT_SIZE)
>>> h1 = blake2b(salt=salt1)
>>> h1.update(msg)
>>> # Вычислить второй хеш с другой случайной солью.
>>> salt2 = os.urandom(blake2b.SALT_SIZE)
>>> h2 = blake2b(salt=salt2)
>>> h2.update(msg)
>>> # Дайджесты различаются.
>>> h1.digest() != h2.digest()
True
Персонализация¶Personalization
Иногда бывает полезно заставить хеш-функцию выдавать разные дайджесты для одного и того же входного значения для разных целей. Цитируя авторов хеш-функции Skein:
Мы рекомендуем всем разработчикам приложений серьезно рассмотреть эту возможность; мы видели много протоколов, где хеш, вычисленный в одной части протокола, может быть использован в совершенно другой части, потому что два хеш-вычисления были выполнены над похожими или связанными данными, и атакующий может заставить приложение сделать входные данные для хешей одинаковыми. Персонализация каждой хеш-функции, используемой в протоколе, однозначно предотвращает такой тип атаки.
(The Skein Hash Function Family, p. 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=
Древовидный режим¶Tree mode
Пример хеширования минимального дерева с двумя листовыми узлами:
10
/ \
00 01
Этот пример использует 64-байтовые внутренние дайджесты и возвращает 32-байтовый конечный дайджест:
>>> from hashlib import blake2b
>>>
>>> FANOUT = 2
>>> DEPTH = 2
>>> LEAF_SIZE = 4096
>>> INNER_SIZE = 64
>>>
>>> buf = bytearray(6000)
>>>
>>> # Левый лист
... 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)
>>> # Правый лист
... 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)
>>> # Корневой узел
... 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'
Авторы¶Credits
BLAKE2 был разработан Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O’Hearn и Christian Winnerlein на основе SHA-3, финалистом которого был BLAKE созданный Jean-Philippe Aumasson, Luca Henzen, Willi Meier и Raphael C.-W. Phan.
В нём используется основной алгоритм из шифра ChaCha, разработанного Daniel J. Bernstein.
Реализация в стандартной библиотеке основана на модуле pyblake2. Её написал Dmitry Chestnykh на основе реализации на C, написанной Samuel Neves. Документация скопирована из pyblake2 и написана Dmitry Chestnykh.
Код на C был частично переписан для Python Christian Heimes.
Следующее заявление о передаче в общественное достояние применимо как к реализации хеш-функции на C, так и к коду расширения и данной документации:
Насколько это возможно по закону, автор(ы) передали все авторские и смежные права на это программное обеспечение в общественное достояние по всему миру. Это программное обеспечение распространяется без каких-либо гарантий.
Копия заявления CC0 о передаче в общественное достояние должна прилагаться к этому программному обеспечению. Если она отсутствует, см. https://creativecommons.org/publicdomain/zero/1.0/.
Следующие люди участвовали в разработке или вносили свои изменения в проект, передавая их в общественное достояние в соответствии с Creative Commons Public Domain Dedication 1.0 Universal:
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
Публикация FIPS 202 о стандарте SHA-3.
- 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 по выработке ключей на основе пароля.