hashlib — Защищенные хэши и дайджесты сообщений

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


Этот модуль реализует общий интерфейс для множества различных алгоритмов безопасного хэширования и дайджеста сообщений. Включены алгоритмы безопасного хэширования FIPS SHA1, SHA224, SHA256, SHA384, SHA512 (определены в the FIPS 180-4 standard), серия SHA-3 (определена в the FIPS 202 standard), а также алгоритм MD5 RSA (определен в internet RFC 1321). Термины «безопасный хэш» и «дайджест сообщений» взаимозаменяемы. Более старые алгоритмы назывались дайджестами сообщений. Современный термин - безопасный хэш.

Примечание

Если вам нужны хэш-функции adler32 или crc32, они доступны в модуле zlib.

Алгоритмы хэширования

Для каждого типа hash существует один метод конструктора. Все они возвращают хэш-объект с одинаковым простым интерфейсом. Например: используйте sha256() для создания хэш-объекта SHA-256. Теперь вы можете ввести в этот объект bytes-like objects (обычно bytes), используя метод update. В любой момент вы можете запросить у него digest для объединения данных, переданных ему до сих пор, используя методы digest() или hexdigest().

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

Конструкторы для алгоритмов хэширования, которые всегда присутствуют в этом модуле, 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). Обратитесь к разделу Attacks on cryptographic hash algorithms и разделу 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 позволяет использовать небезопасные и заблокированные алгоритмы хэширования в средах с ограниченным доступом. False указывает, что алгоритм хэширования не используется в контексте безопасности, например, в качестве некриптографической функции одностороннего сжатия.

Изменено в версии 3.9: Hashlib теперь использует SHA 3 и 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)

Это универсальный конструктор, который принимает строку 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», несмотря на то, что некоторые поставщики, работающие с исходным кодом, предлагают странную «совместимую с FIPS» сборку Python, которая его исключает.

Добавлено в версии 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-like object. Повторные вызовы эквивалентны однократному вызову с объединением всех аргументов: m.update(a); m.update(b) эквивалентно m.update(a+b).

Изменено в версии 3.1: Выпущен Python GIL, позволяющий запускать другие потоки во время обновления хэша данных размером более 2047 байт при использовании алгоритмов хэширования, предоставляемых OpenSSL.

hash.digest()

Возвращает краткий обзор данных, переданных на данный момент методу update(). Это объект bytes размером digest_size, который может содержать байты во всем диапазоне от 0 до 255.

hash.hexdigest()

Как digest(), за исключением того, что дайджест возвращается в виде строкового объекта двойной длины, содержащего только шестнадцатеричные цифры. Это может использоваться для безопасного обмена значением в электронной почте или других недвоичных средах.

hash.copy()

Возвращает копию («клон») хэш-объекта. Это может быть использовано для эффективного вычисления сводных данных, имеющих общую начальную подстроку.

ВЗБАЛТЫВАЙТЕ дайджесты переменной длины

hashlib.shake_128([data, ]*, usedforsecurity=True)
hashlib.shake_256([data, ]*, usedforsecurity=True)

Алгоритмы shake_128() и shake_256() предоставляют дайджесты переменной длины с длиной в битах//2 до 128 или 256 бит безопасности. Таким образом, для их методов дайджеста требуется длина. Максимальная длина не ограничена алгоритмом встряхивания.

shake.digest(length)

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

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

Функция предоставляет функцию получения ключа на основе пароля PKCS#5. Она использует HMAC в качестве псевдослучайной функции.

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

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

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 должны быть bytes-like objects. Приложениям и библиотекам следует ограничить password разумной длиной (например, 1024). значение salt должно составлять около 16 или более байт из соответствующего источника, например os.urandom().

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

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

ЧЕРНЫЙ ЦВЕТ2

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

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

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

BLAKE 2 поддерживает ** ключевой режим ** (более быструю и простую замену 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. При необходимости они принимают следующие общие параметры:

  • данные: начальный фрагмент данных для хэширования, который должен быть bytes-like object. Он может быть передан только как позиционный аргумент.

  • digest_size: размер выходного дайджеста в байтах.

  • ключ: ключ для кэшированного хэширования (до 64 байт для BLAKE2b, до 32 байт для BLAKE2s).

  • соль: соль для рандомизированного хэширования (до 16 байт для BLAKE2b, до 8 байт для BLAKE2s).

  • person: строка персонализации (до 16 байт для BLAKE2b, до 8 байт для BLAKE2s).

В следующей таблице приведены ограничения для общих параметров (в байтах).:

Хэш

размер дайджеста

len(ключ)

лен(соль)

лен(человек)

BLAKE2b (Черный)

64

64

16

16

БЛЕЙК2с

32

32

8

8

Примечание

Спецификация BLACK 2 определяет постоянные длины для параметров salt и персонализации, однако для удобства эта реализация принимает байтовые строки любого размера вплоть до указанной длины. Если длина параметра меньше указанной, он дополняется нулями, таким образом, например, b'salt' и b'salt\x00' - это одно и то же значение. (Это не относится к key.)

Эти размеры доступны в виде модуля constants, описанного ниже.

Функции конструктора также принимают следующие параметры хэширования дерева:

  • разветвление: разветвление (от 0 до 255, 0 при неограниченном количестве, 1 в последовательном режиме).

  • глубина: максимальная глубина дерева (от 1 до 255, 255 при неограниченном количестве, 1 в последовательном режиме).

  • размер листа: максимальная длина листа в байтах (от 0 до 2**32-1, 0, если не ограничено или в последовательном режиме).

  • node_offset: смещение узла (от 0 до 2**64-1 для BLAKE2b, от 0 до 2**48-1 для BLAKE2s, 0 для первого, крайнего левого листа или в последовательном режиме).

  • node_depth: глубина узла (от 0 до 255, 0 для листьев или в последовательном режиме).

  • inner_size: внутренний размер дайджеста (от 0 до 64 для BLAKE2b, от 0 до 32 для BLAKE2s, 0 в последовательном режиме).

  • last_node: логическое значение, указывающее, является ли обрабатываемый узел последним (False для последовательного режима).

Объяснение параметров древовидного режима.

Смотрите раздел 2.10 в BLAKE2 specification для подробного обзора хеширования дерева.

Константы

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'

Использование различных размеров дайджеста

BLADE 2 имеет настраиваемый размер дайджестов до 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'

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

Хэширование с использованием ключа может использоваться для аутентификации в качестве более быстрой и простой замены Hash-based message authentication code (HMAC). BLADE 2 можно безопасно использовать в режиме prefix-MAC благодаря свойству indifferentiability, унаследованному от 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

Несмотря на то, что существует собственный режим хэширования с ключом, BLACK 2, конечно, можно использовать в конструкции 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 «Randomized Hashing for Digital Signatures»)

В BLAKE2 соль обрабатывается как одноразовый ввод в хэш-функцию во время инициализации, а не как ввод в каждую функцию сжатия.

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

**Соленое хэширование* (или просто хэширование) с помощью BLAKE2 или любой другой криптографической хэш-функции общего назначения, такой как SHA-256, не подходит для хэширования паролей. Дополнительную информацию смотрите в разделе BLAKE2 FAQ.

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

Мы рекомендуем всем разработчикам приложений серьезно подумать об этом; мы видели много протоколов, в которых хэш, вычисленный в одной части протокола, может быть использован в совершенно другой части, потому что два вычисления хэша были выполнены с аналогичными или связанными данными, и злоумышленник может заставить приложение ввести хэш то же самое. Персонализация каждой хэш-функции, используемой в протоколе, в конечном итоге останавливает этот тип атаки.

(The Skein Hash Function Family, стр. 21)

БЛЕЙК 2 можно персонализировать, передав байты в аргумент 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 был разработан * Жан-Филиппом Омассоном*, * Сэмюэлем Невесом*, Зооко Уилкокс-О’Хирн и * Кристианом Виннерлейном* на основе SHA-3-финалиста BLAKE, созданного Жан-Филиппом Омассоном, Лукой Хензеном, Вилли Мейером и Рафаэлем К.-У. Фан.

Он использует базовый алгоритм от ChaCha cipher, разработанный * Дэниелом Дж. Бернштейном*.

Реализация stdlib основана на модуле pyblake2. Он был написан Дмитрием Честных на основе реализации C, написанной Сэмюэлем Невесом. Документация была скопирована из pyblake2 и написана Дмитрием Честных.

Код на C был частично переписан для Python Кристианом Хеймесом (Christian Heimes).

Приведенная ниже информация о доступе к общественному достоянию относится как к реализации хэш-функции на языке Си, коду расширения, так и к данной документации:

Насколько это возможно в соответствии с законом, автор(ы) передал все авторские и смежные права на данное программное обеспечение в общественное достояние по всему миру. Данное программное обеспечение распространяется без каких-либо гарантий.

Вместе с этим программным обеспечением вы должны были получить копию документа CC0, являющегося общественным достоянием. Если нет, смотрите раздел https://creativecommons.org/publicdomain/zero/1.0/.

Следующие люди помогли с разработкой или внесли свои изменения в проект и сделали его общественным достоянием в соответствии с соглашением Creative Commons об общественном достоянии 1.0 Universal:

  • ** Александр Соколовский*

См.также

Модуль hmac

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

Модуль 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 по получению ключей на основе паролей.

Вернуться на верх