Spec-Zone.ru › Python 3.13

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.

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

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

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

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

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

Чтобы получить дайджест байтовой строки b"Nobody inspects the spammish repetition":

>>> import hashlib
>>> m = hashlib.sha256()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
>>> m.digest()
b'\x03\x1e\xdd}Ae\x15\x93\xc5\xfe\\\x00o\xa5u+7\xfd\xdf\xf7\xbcN\x84:\xa6\xaf\x0c\x95\x0fK\x94\x06'
>>> m.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'

В более компактном виде:

>>> hashlib.sha256(b"Nobody inspects the spammish repetition").hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'

Конструкторы

hashlib.new(name, [data, ]*, usedforsecurity=True)

Универсальный конструктор, который принимает строку name с именем нужного алгоритма в качестве первого параметра. Он также позволяет обращаться к перечисленным выше хеш-функциям и другим алгоритмам, которые может предоставлять ваша библиотека OpenSSL.

Использование new() с именем алгоритма:

>>> h = hashlib.new('sha256')
>>> h.update(b"Nobody inspects the spammish repetition")
>>> h.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'
hashlib.md5([data, ]*, usedforsecurity=True)
hashlib.sha1([data, ]*, usedforsecurity=True)
hashlib.sha224([data, ]*, usedforsecurity=True)
hashlib.sha256([data, ]*, usedforsecurity=True)
hashlib.sha384([data, ]*, usedforsecurity=True)
hashlib.sha512([data, ]*, usedforsecurity=True)
hashlib.sha3_224([data, ]*, usedforsecurity=True)
hashlib.sha3_256([data, ]*, usedforsecurity=True)
hashlib.sha3_384([data, ]*, usedforsecurity=True)
hashlib.sha3_512([data, ]*, usedforsecurity=True)

Именованные конструкторы, такие как эти, работают быстрее, чем передача имени алгоритма в new().

Атрибуты

Модуль hashlib предоставляет следующие константные атрибуты:

hashlib.algorithms_guaranteed

Множество имён алгоритмов хеширования, поддержку которых этот модуль гарантирует на всех платформах. Обратите внимание, что «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.13.4: Теперь вызывает исключение 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. Обоснование и рекомендации по выбору параметров для вашего приложения приведены в разделе Приложение 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 — коэффициент затрат CPU/памяти, 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.

Реализация в стандартной библиотеке основана на модуле 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–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/hashlib.html

Spec-Zone.ru

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