Spec-Zone.ru › Python 3.14

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. Теперь этот объект можно передавать объекты, подобные байтовым (обычно bytes), используя метод update. В любой момент можно получить дайджест конкатенации всех переданных ему на данный момент данных с помощью метода digest() или hexdigest().

Для поддержки многопоточности интерпретатор Python освобождает GIL при вычислении хеша, если конструктору или методу .update за один раз передано более 2047 байт данных.

Конструкторы алгоритмов хеширования, которые всегда доступны в этом модуле: sha1(), sha224(), sha256(), sha384(), sha512(), sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256(), blake2b() и blake2s(). Обычно доступен и md5(), хотя он может отсутствовать или быть заблокирован, если вы используете редкую сборку Python, «совместимую с FIPS». Эти алгоритмы соответствуют algorithms_guaranteed.

Дополнительные алгоритмы могут быть доступны, если hashlib вашего дистрибутива Python был скомпонован со сборкой 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 указывает, что алгоритм хеширования не используется в контексте безопасности, например как некриптографическая односторонняя функция сжатия.

Изменено в версии 3.9: Теперь hashlib использует реализации SHA3 и SHAKE из OpenSSL, если они там доступны.

Изменено в версии 3.12: Для алгоритмов MD5, SHA1, SHA2 или SHA3, которые не поддерживаются связанной библиотекой OpenSSL, используется проверенная реализация из проекта 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

Множество, содержащее имена алгоритмов хеширования, поддержку которых этот модуль гарантирует на всех платформах. Обратите внимание, что «md5» входит в этот список, несмотря на то что некоторые поставщики предлагают необычную сборку Python, «совместимую с FIPS», в которой этот алгоритм исключён.

Добавлено в версии 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(). Это объект bytes размером 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 бит. Поэтому для их методов digest требуется указать длину. Максимальная длина не ограничена алгоритмом 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'

Хеширование файлов

Модуль 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.11.

Изменено в версии 3.14: Теперь вызывает исключение BlockingIOError, если файл открыт в неблокирующем режиме. Ранее в дайджест добавлялись лишние нулевые байты.

Вывод ключа

Алгоритмы вывода и растяжения ключа предназначены для безопасного хеширования паролей. Простые алгоритмы, такие как sha1(password), не защищены от атак перебором. Хорошая функция хеширования паролей должна настраиваться, работать медленно и использовать соль.

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

Эта функция реализует функцию вывода ключа на основе пароля 2, определённую в PKCS#5. В качестве псевдослучайной функции она использует HMAC.

Строка hash_name — это имя нужного алгоритма хеширования для HMAC, например «sha1» или «sha256». Аргументы password и salt интерпретируются как буферы байтов. Приложениям и библиотекам следует ограничивать password разумной длиной (например, 1024). Размер salt должен составлять около 16 байт или больше; её следует получать из надёжного источника, например os.urandom().

Число iterations следует выбирать с учётом алгоритма хеширования и вычислительной мощности. По состоянию на 2022 год рекомендуется использовать сотни тысяч итераций SHA-256. Обоснование и рекомендации по выбору оптимального значения для вашего приложения приведены в разделе Appendix A.2.2 документа NIST-SP-800-132. Подробные объяснения также содержатся в ответах на вопрос о рекомендуемом числе итераций PBKDF2 на Stack Exchange.

dklen — длина выведенного ключа в байтах. Если dklen равен None, используется размер дайджеста алгоритма хеширования hash_name, например 64 для SHA-512.

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

Эта функция реализует функцию вывода ключа scrypt на основе пароля, определённую в RFC 7914.

Аргументы password и salt должны быть объектами, подобными байтовым. Приложениям и библиотекам следует ограничивать password разумной длиной (например, 1024). Размер salt должен составлять около 16 байт или больше; её следует получать из надёжного источника, например os.urandom().

n — коэффициент затрат ЦП/памяти, r — размер блока, p — коэффициент параллелизации, а maxmem ограничивает объём используемой памяти (в OpenSSL 1.1.0 по умолчанию — 32 МиБ). dklen — длина выведенного ключа в байтах.

Добавлено в версии 3.6.

BLAKE2

BLAKE2 — это криптографическая хеш-функция, определённая в RFC 7693, которая имеет два варианта:

  • BLAKE2b, оптимизированная для 64-разрядных платформ и создающая дайджесты размером от 1 до 64 байт,
  • BLAKE2s, оптимизированная для 8- и 32-разрядных платформ и создающая дайджесты размером от 1 до 32 байт.

BLAKE2 поддерживает режим с ключом (более быструю и простую замену HMAC), хеширование с солью, персонализацию и древовидное хеширование.

Объекты хеша из этого модуля следуют API объектов hashlib стандартной библиотеки.

Создание объектов хеша

Новые объекты хеша создаются вызовом функций-конструкторов:

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: начальный фрагмент данных для хеширования, который должен быть объектом, подобным bytes. Его можно передать только как позиционный аргумент.
  • 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: число дочерних узлов (от 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 для последовательного режима).
Explanation of tree mode parameters.

Подробный обзор древовидного хеширования см. в разделе 2.10 спецификации BLAKE2.

Константы

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 можно настраивать: до 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'

Хеширование с ключом

Хеширование с ключом можно использовать для аутентификации как более быструю и простую замену кода аутентификации сообщений на основе хеша (HMAC). BLAKE2 можно безопасно использовать в режиме префиксного 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'

В качестве практического примера веб-приложение может симметрично подписывать файлы 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.

>>> 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 на основе 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 о передаче в общественное достояние 1.0:

  • Alexandr Sokolovskiy

См. также

Module hmac

Модуль для создания кодов аутентификации сообщений с использованием хешей.

Module 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 по выработке ключей на основе паролей.

© 2001 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/library/hashlib.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API