Spec-Zone.ru › Python 3.12

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 (обычно 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.

Дополнительные алгоритмы также могут быть доступны, если дистрибутив Python с модулем hashlib собран с OpenSSL, предоставляющим эти алгоритмы. Доступность остальных алгоритмов не гарантируется во всех установках; к ним можно обращаться только по имени через new(). См. algorithms_available.

Предупреждение

Для некоторых алгоритмов известны уязвимости, связанные с коллизиями хешей (в том числе для MD5 и SHA1). См. атаки на криптографические хеш-функции и раздел см. также hashlib в конце этого документа.

Добавлено в версии 3.6: Добавлены конструкторы SHA3 (Keccak) и SHAKE: sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256(). Также добавлены blake2b() и blake2s().

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

Изменено в версии 3.9: Теперь 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)

Обновляет объект хеширования объектом типа bytes. Несколько вызовов эквивалентны одному вызову с объединёнными аргументами: 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 бит. Поэтому для их методов дайджеста необходимо указать длину. Алгоритм 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(), и тому подобным. Функция может обходить средства ввода-вывода 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)

Эта функция реализует функцию вывода ключа 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 должны быть объектами, подобными bytes. Приложениям и библиотекам следует ограничивать 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: начальный блок данных для хэширования, который должен быть объектом, подобным байтовой последовательности. Его можно передать только как позиционный аргумент.
  • 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.

Реализация в 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 о передаче в общественное достояние версии 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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/hashlib.html

Spec-Zone.ru

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