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для последовательного режима).
Подробный обзор древовидного хэширования см. в разделе 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
См. также
-
Modulehmac -
Модуль для создания кодов аутентификации сообщений с помощью хеш-функций.
-
Modulebase64 -
Ещё один способ кодировать двоичные хеши для сред, не поддерживающих двоичные данные.
- 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