Spec-Zone.ru › Python 3.11

hashlib — Безопасные хеши и дайджесты сообщений

Исходный код: Lib/hashlib.py

Этот модуль реализует общий интерфейс для многих различных алгоритмов безопасного хеширования и дайджестов сообщений. В него входят алгоритмы безопасного хеширования FIPS SHA1, SHA224, SHA256, SHA384, SHA512 (определенные в стандарте FIPS 180-4), семейство SHA-3 (определенное в стандарте FIPS 202), а также алгоритм MD5 RSA (определенный в интернет-документе 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() обычно также доступен, хотя может отсутствовать или быть заблокированным, если вы используете редкую «FIPS-совместимую» сборку Python. Они соответствуют algorithms_guaranteed.

Дополнительные алгоритмы могут быть доступны, если ваша дистрибуция 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().

В версии 3.6: Были добавлены blake2b() и blake2s().

Изменено в версии 3.9: Все конструкторы hashlib принимают ключевой аргумент usedforsecurity со значением по умолчанию True. Ложное значение позволяет использовать небезопасные и заблокированные алгоритмы хеширования в ограниченных средах. False указывает, что алгоритм хеширования не используется в контексте безопасности, например, в качестве некриптографической односторонней функции сжатия.

Изменено в версии 3.9: Hashlib теперь использует SHA3 и SHAKE из OpenSSL, если он доступен.

Использование

Чтобы получить дайджест байтовой строки 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, которая его исключает.

В версии 3.2.

hashlib.algorithms_available

Множество, содержащее имена алгоритмов хеширования, доступных в работающей интерпретации Python. Эти имена будут распознаны при передаче в new(). algorithms_guaranteed всегда будет подмножеством. Один и тот же алгоритм может появляться в этом множестве несколько раз под разными именами (благодаря OpenSSL).

В версии 3.2.

END_OF_DOCUMENT_MARKER

Объекты хешей

Следующие значения предоставляются в качестве постоянных атрибутов объектов хешей, возвращаемых конструкторами:

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

Изменено в версии 3.1: Блокировка интерпретатора Python (GIL) освобождается, чтобы позволить другим потокам выполняться во время обновления хеша для данных размером более 2047 байтов при использовании алгоритмов хеширования, предоставляемых OpenSSL.

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 экземпляров, объекты SocketIO из socket.socket.makefile() и аналогичных. Функция может обойти ввод-вывод Python и использовать дескриптор файла из 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. Для обоснования выбора и того, как выбрать лучший вариант для вашего приложения, ознакомьтесь с Приложением 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  # Application specific, read above.
>>> dk = pbkdf2_hmac('sha256', b'password', b'bad salt'*2, our_app_iters)
>>> dk.hex()
'15530bba69924174860db778f2c6f8104d3aaf9d26241840c8c4a641c8d000a9'

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

Примечание

Быстрое реализация pbkdf2_hmac доступно с OpenSSL. Реализация Python использует встроенную версию hmac. Она примерно в три раза медленнее и не освобождает GIL.

Устаревшая с версии 3.10: Медленная реализация Python для pbkdf2_hmac устарела. В будущем функция будет доступна только при компиляции Python с OpenSSL.

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 ограничивает память (по умолчанию 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.

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

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

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 определяет постоянные длины для параметров salt и personalization, однако, для удобства, эта реализация принимает байтовые строки любого размера до указанной длины. Если длина параметра меньше указанной, она дополняется нулями, таким образом, например, 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 может безопасно использоваться в режиме 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'

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

Реализация stdlib основана на модуле 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

См. также

Module hmac

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

Module base64

Ещё один способ кодирования двоичных хешей для сред, не использующих бинарные данные.

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

Публикация FIPS 180-4 по алгоритмам безопасного хеширования.

https://csrc.nist.gov/publications/detail/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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/hashlib.html

END_OF_DOCUMENT_MARKER

Spec-Zone.ru

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