hashlib --- Algorithmes de hachage sécurisés et synthèse de messages

Code source : Lib/hashlib.py


Ce module implémente une interface commune à différents algorithmes de hachage sécurisés et de synthèse de messages. Sont inclus les algorithmes standards FIPS de hachage SHA1, SHA224, SHA256, SHA384, et SHA512 (définis dans le le standard FIPS 180-4), la série SHA-3 (définis dans le standard FIPS 202), ainsi que l'algorithme MD5 de RSA (défini par la RFC 1321). Les termes « algorithmes de hachage sécurisé » et « algorithme de synthèse de message » sont interchangeables. Les anciens algorithmes étaient appelés « algorithmes de synthèse de messages ». Le terme moderne est « algorithme de hachage sécurisé ».

Note

Si vous préférez utiliser les fonctions de hachage adler32 ou crc32, elles sont disponibles dans le module zlib.

Algorithmes de hachage

Il y a un constructeur nommé selon chaque type de calcul d'empreinte (hash). Tous renvoient un objet haché avec la même interface. Par exemple : utilisez sha256() pour créer un objet de calcul d'empreinte avec l'algorithme SHA-256. Vous pouvez maintenant utiliser cet objet avec des objets octets-compatibles (normalement des bytes) en utilisant la méthode update. À tout moment vous pouvez demander l'empreinte (aussi appelée le digest ou le condensat) de la concaténation des données fournies en utilisant les méthodes digest() ou hexdigest().

pour de meilleures performances avec de multiples fils d'exécution, le GIL Python est relâché pour des données dont la taille est supérieure à 2047 octets lors de leur création ou leur mise à jour (méthode .update.).

Les constructeurs pour les algorithmes de hachage qui sont toujours présents dans ce module sont sha1(), sha224(), sha256(), sha384(), sha512(), sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256(), blake2b(), et blake2s(). md5() est normalement disponible aussi, mais il peut être manquant ou bloqué si vous utilisez une forme rare de Python « conforme FIPS ». Cette liste correspond au résultat de la fonction algorithms_guaranteed.

Additional algorithms may also be available if your Python distribution's hashlib was linked against a build of OpenSSL that provides others. Others are not guaranteed available on all installations and will only be accessible by name via new(). See algorithms_available.

Avertissement

Certains algorithmes ont des faiblesses connues relatives à la collision (MD5 et SHA1 inclus). Se référer à Fonction de hachage cryptographique et à la section Voir aussi à la fin du document.

Ajouté dans la version 3.6: les constructeurs SHA3 (Keccak) et SHAKE sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256() ont été ajoutés. blake2b() et blake2s() ont été ajoutés.

Modifié dans la version 3.9: tous les constructeurs de hashlib prennent un argument mot-clé uniquement usedforsecurity avec la valeur par défaut True. Une valeur fausse permet l'utilisation d'algorithmes de hachage non sécurisés et bloqués dans des environnements restreints. False indique que l'algorithme de hachage ne sera pas utilisé dans un contexte de sécurité, par exemple en tant que fonction de compression à sens unique non cryptographique.

Modifié dans la version 3.9: Hashlib utilise désormais SHA3 et SHAKE d'OpenSSL s'il les fournit.

Modifié dans la version 3.12: For any of the MD5, SHA1, SHA2, or SHA3 algorithms that the linked OpenSSL does not provide we fall back to a verified implementation from the HACL* project.

Utilisation

To obtain the digest of the byte string 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'

En plus condensé :

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

Constructeurs

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

Is a generic constructor that takes the string name of the desired algorithm as its first parameter. It also exists to allow access to the above listed hashes as well as any other algorithms that your OpenSSL library may offer.

Using new() with an algorithm name:

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

Named constructors such as these are faster than passing an algorithm name to new().

Attributes

Hashlib fournit les constantes de module suivantes :

hashlib.algorithms_guaranteed

Ensemble contenant les noms des algorithmes de hachage garantis d'être implémentés par ce module sur toutes les plate-formes. Notez que md5 est dans cette liste bien que certains éditeurs diffusent une implémentation Python dont la bibliothèque « compatible FIPS » le bloque.

Ajouté dans la version 3.2.

hashlib.algorithms_available

Ensemble contenant les noms des algorithmes de hachage disponibles dans l'interpréteur Python. Ces noms sont reconnus lorsqu'ils sont passés à la fonction new(). algorithms_guaranteed est toujours un sous-ensemble. Le même algorithme peut apparaître plusieurs fois dans cet ensemble sous un nom différent (grâce à OpenSSL).

Ajouté dans la version 3.2.

Objets de calcul d'empreinte

Les valeurs suivantes sont fournies en tant qu'attributs constants des objets de calcul d'empreintes renvoyés par les constructeurs :

hash.digest_size

La taille du hash résultant en octets.

hash.block_size

La taille interne d'un bloc de l'algorithme de hachage en octets.

L'objet de hachage possède les attributs suivants :

hash.name

Le nom canonique de cette fonction de hachage, toujours en minuscule et que vous pouvez toujours transmettre à la fonction new() pour créer un autre objet de calcul d'empreinte de ce type.

Modifié dans la version 3.4: l'attribut name est présent dans CPython depuis sa création, mais n'était pas spécifié formellement jusqu'à Python 3.4, il peut ne pas exister sur certaines plate-formes.

L'objet de calcul d'empreinte possède les méthodes suivantes :

hash.update(data)

Met à jour l'objet de hachage avec bytes-like object. Les appels répétés sont équivalents à un simple appel avec la concaténation de tous les arguments : m.update(a); m.update(b) est équivalent à m.update(a+b).

hash.digest()

Renvoie l'empreinte (le hash) des données passées à la méthode update(). C'est un objet de type bytes de taille digest_size qui contient des octets dans l'intervalle 0 à 255.

hash.hexdigest()

Comme la méthode digest() sauf que l'empreinte renvoyée est une chaîne de caractères dont la longueur est double, contenant seulement des chiffres hexadécimaux. Elle peut être utilisée pour échanger sans risque des valeurs dans les e-mails ou dans les environnements non binaires.

hash.copy()

Renvoie une copie ("clone") de l'objet de calcul de hachage. Cela peut être utilisé pour calculer efficacement des empreintes de données qui commencent par la même sous-chaine.

Empreintes de messages de taille variable SHAKE

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

Les algorithmes shake_128() et shake_256() produisent des empreintes (ou condensats) de longueur variable avec des longueurs_en_bits // 2 jusqu'à 128 ou 256 bits. Leurs méthodes de calcul d'empreinte requièrent une longueur. Les longueurs maximales ne sont pas limitées par l'algorithme SHAKE.

shake.digest(length)

Renvoie l'empreinte des données passées à la méthode update(). C'est un objet de type bytes de taille length qui contient des octets dans l'intervalle 0 à 255.

shake.hexdigest(length)

Comme la méthode digest() sauf que l'empreinte renvoyée est une chaîne de caractères dont la longueur est double, contenant seulement des chiffres hexadécimaux. Elle peut être utilisée pour échanger sans risque des valeurs dans les e-mails ou dans les environnements non binaires.

Exemple :

>>> h = hashlib.shake_256(b'Nobody inspects the spammish repetition')
>>> h.hexdigest(20)
'44709d6fcb83d92a76dcb0b668c98e1b1d3dafe7'

Calcul d'empreinte (ou hachage) de fichiers

Le module hashlib fournit une fonction utilitaire pour calculer efficacement l'empreinte (aussi appelée condensat) d'un fichier ou d'un objet fichier-compatible.

hashlib.file_digest(fileobj, digest, /)

Renvoie un objet de calcul d'empreinte qui a été mis à jour avec le contenu de fileobj.

fileobj doit être un objet fichier-compatible ouvert en lecture en mode binaire. Sont acceptés les instances d'objets fichiers produites par la fonction native open(), BytesIO, les objets connecteurs produits par socket.socket.makefile() et similaires. La fonction peut court-circuiter les entrées-sorties de Python et utiliser directement le descripteur de fichier de fileno(). Vous devez supposer que fileobj est dans un état inconnu après le retour de cette fonction ou si elle a levé une exception. C'est à l'appelant de fermer fileobj.

digest doit être un nom d'algorithme de hachage fourni en tant que str, un constructeur de hachage ou un appelable qui renvoie un objet de hachage.

Exemple :

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

Ajouté dans la version 3.11.

Dérivation de clé

Les algorithmes de dérivation de clés et d'étirement de clés sont conçus pour le hachage sécurisé de mots de passe. Des algorithmes naïfs comme sha1(password) ne sont pas résistants aux attaques par force brute. Une bonne fonction de hachage doit être paramétrable, lente et inclure un salage.

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

La fonction fournit une fonction de dérivation conforme à PKCS#5 (Public Key Cryptographic Standards #5 v2.0). Elle utilise HMAC comme fonction de génération d'un pseudo-aléa.

La chaîne de caractères hash_name est le nom de l'algorithme de hachage désiré pour le HMAC, par exemple "sha1" ou "sha256". password et salt sont interprétés comme des tampons d'octets. Les applications et bibliothèques doivent limiter password à une longueur raisonnable (comme 1024). salt doit être de 16 octets ou plus et provenir d'une source correcte, e.g. os.urandom().

Le nombre d'itérations doit être choisi en fonction de l'algorithme de hachage et de la puissance de calcul. À partir de 2022, des centaines de milliers d'itérations de SHA-256 sont suggérées. Pour savoir pourquoi et comment choisir ce qui convient le mieux à votre application, lisez l'annexe A.2.2 du NIST-SP-800-132 (ressource en anglais). Les réponses contenues dans la question sur le site stackexchange nombre d'itérations recommandées lorsqu'on utilise pbkdf2 (page en anglais) expliquent tout en détail.

dklen est la longueur de la clé dérivée. Si dklen vaut None alors Python utilise la taille du condensat produit par l'algorithme de hachage hash_name, par exemple 64 pour 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'

Function only available when Python is compiled with OpenSSL.

Ajouté dans la version 3.4.

Modifié dans la version 3.12: Function now only available when Python is built with OpenSSL. The slow pure Python implementation has been removed.

hashlib.scrypt(password, *, salt, n, r, p, maxmem=0, dklen=64)

La fonction fournit la fonction de dérivation de clé scrypt comme définie dans la RFC 7914.

password et salt doivent être des objets octets-compatibles. Les applications et bibliothèques doivent limiter password à une longueur raisonnable (par ex. 1024). salt doit être de 16 octets ou plus et provenir d'une source correcte, par ex. os.urandom().

n est le facteur de coût CPU/Mémoire, r la taille de bloc, p le facteur de parallélisation et maxmem limite l'utilisation de la mémoire (OpenSSL 1.1.0 limite à 32 Mio par défaut). dklen est la longueur de la clé dérivée en octets.

Ajouté dans la version 3.6.

BLAKE2

BLAKE2 est une fonction de hachage cryptographique définie dans la RFC 7693 et disponible en deux versions :

  • BLAKE2b, optimisée pour les plates-formes 64 bits et produisant des condensats de toutes tailles entre 1 et 64 octets,

  • BLAKE2s, optimisée pour les plates-formes de 8 à 32 bits et produisant des empreintes de toutes tailles entre 1 et 32 octets.

BLAKE2 gère diverses fonctionnalités comme le keyed mode (plus rapide et plus simple que HMAC), salted hashing, personalization et le tree hashing.

Les objets de calcul d'empreinte de ce module suivent l'API des objets du module hashlib de la bibliothèque standard.

Création d'objets de calcul d'empreinte

Les nouveaux objets de calcul d'empreinte sont créés en appelant les constructeurs :

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)

Ces fonctions produisent l'objet de calcul d'empreinte correspondant aux algorithmes BLAKE2b ou BLAKE2s. Elles prennent ces paramètres optionnels :

  • data : morceau initial de données à hacher, qui doit être un objet octets-compatible. Il ne peut être passé que comme argument positionnel.

  • digest_size : taille en octets de l'empreinte produite.

  • key : clé pour les codes d'authentification de message keyed hashing (jusqu'à 64 octets pour BLAKE2b, jusqu'à 32 octets pour BLAKE2s).

  • salt : sel pour le hachage randomisé randomized hashing (jusqu'à 16 octets pour BLAKE2b, jusqu'à 8 octets pour BLAKE2s).

  • person : chaîne de personnalisation (jusqu'à 16 octets pour BLAKE2b, jusqu'à 8 octets pour BLAKE2s).

Le tableau suivant présente les limites des paramètres généraux (en octets) :

Hash

digest_size

len(key)

len(salt)

len(person)

BLAKE2b

64

64

16

16

BLAKE2s

32

32

8

8

Note

les spécifications de BLAKE2 définissent des longueurs constantes pour les sel et chaînes de personnalisation. Toutefois, par commodité, cette implémentation accepte des chaînes d'octets de n'importe quelle taille jusqu'à la longueur spécifiée. Si la longueur du paramètre est moindre par rapport à celle spécifiée, il est complété par des zéros. Ainsi, par exemple, b'salt' et b'salt\x00' sont la même valeur (ce n'est pas le cas pour key).

Ces tailles sont disponibles en tant que constantes du module et décrites ci-dessous.

Les fonctions constructeurs acceptent aussi les paramètres suivants pour le calcul d'empreintes en mode arbre :

  • fanout : étalement (0 à 255, 0 si illimité, 1 correspond au mode séquentiel).

  • depth : profondeur maximale de l'arbre (1 à 255, 255 si illimité, 1 correspond au mode séquentiel).

  • leaf_size : taille maximale en octets d'une feuille (0 à 2**32-1, 0 si illimité ou en mode séquentiel).

  • node_offset : décalage du nœud (0 à 2**64-1 pour BLAKE2b, 0 à 2**48-1 pour BLAKE2s, 0 pour la première feuille la plus à gauche, ou en mode séquentiel).

  • node_depth : profondeur du nœud (0 à 255, 0 pour les feuilles, ou en mode séquentiel).

  • inner_size : taille de l'empreinte interne (0 à 64 pour BLAKE2b, 0 à 32 pour BLAKE2s, 0 en mode séquentiel).

  • last_node : booléen indiquant si le nœud traité est le dernier (False pour le mode séquentiel).

Explication des paramètres du mode arbre.

Voir la section 2.10 dans BLAKE2 specification pour une approche globale du hachage en mode arbre.

Constantes

blake2b.SALT_SIZE
blake2s.SALT_SIZE

Longueur du sel (longueur maximale acceptée par les constructeurs).

blake2b.PERSON_SIZE
blake2s.PERSON_SIZE

Longueur de la chaîne de personnalisation (longueur maximale acceptée par les constructeurs).

blake2b.MAX_KEY_SIZE
blake2s.MAX_KEY_SIZE

Taille maximale de clé.

blake2b.MAX_DIGEST_SIZE
blake2s.MAX_DIGEST_SIZE

Taille maximale du message que peut fournir la fonction de hachage.

Exemples

Hachage simple

Pour calculer l'empreinte (ou hash) d'une quantité de données, vous devez d'abord construire un objet de calcul d'empreinte en appelant la fonction constructeur appropriée (blake2b() or blake2s()), ensuite le mettre à jour avec les données en appelant la méthode update() sur l'objet, et, pour finir, récupérer l'empreinte du message en appelant la méthode digest() (ou hexdigest() pour les chaînes hexadécimales).

>>> from hashlib import blake2b
>>> h = blake2b()
>>> h.update(b'Hello world')
>>> h.hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'

En plus court, vous pouvez passer directement au constructeur, comme argument positionnel, le premier morceau du message pour le mettre directement à jour :

>>> from hashlib import blake2b
>>> blake2b(b'Hello world').hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'

Vous pouvez appeler la méthode hash.update() autant de fois que nécessaire pour mettre à jour l'empreinte de manière itérative :

>>> from hashlib import blake2b
>>> items = [b'Hello', b' ', b'world']
>>> h = blake2b()
>>> for item in items:
...     h.update(item)
...
>>> h.hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'

Production de tailles d'empreintes différentes

BLAKE2 permet de configurer la taille des empreintes jusqu'à 64 octets pour BLAKE2b et jusqu'à 32 octets pour BLAKE2s. Par exemple, pour remplacer SHA-1 par BLAKE2b sans changer la taille de la sortie, nous pouvons dire à BLAKE2b de produire une empreinte de 20 octets :

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

Les objets de calcul d'empreinte initialisés avec des tailles d'empreintes différentes ont des sorties complètement différentes (les condensats courts ne sont pas des préfixes de condensats plus longs) ; BLAKE2b et BLAKE2s produisent des sorties différentes même si les longueurs de sortie sont les mêmes :

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

Hachage avec clé – Code d'authentification de message

Le hachage avec clé (keyed hashing en anglais) est une alternative plus simple et plus rapide à un code d’authentification de message de hachage à clé (HMAC). BLAKE2 peut être utilisé de manière sécurisée dans le mode préfixe MAC grâce à la propriété d'indifférentiabilité héritée de BLAKE.

Cet exemple montre comment obtenir un code d'authentification de message de 128 bits (en hexadécimal) pour un message b'message data' avec la clé b'pseudorandom key' :

>>> from hashlib import blake2b
>>> h = blake2b(key=b'pseudorandom key', digest_size=16)
>>> h.update(b'message data')
>>> h.hexdigest()
'3d363ff7401e02026f4a4687d4863ced'

Comme exemple pratique, une application web peut chiffrer symétriquement les cookies envoyés aux utilisateurs et les vérifier plus tard pour être certaine qu'ils n'ont pas été altérés :

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

Même s'il possède en natif la création de code d'authentification de message (MAC), BLAKE2 peut, bien sûr, être utilisé pour construire un HMAC en combinaison avec le module hmac :

>>> import hmac, hashlib
>>> m = hmac.new(b'secret key', digestmod=hashlib.blake2s)
>>> m.update(b'message')
>>> m.hexdigest()
'e3c8102868d28b5ff85fc35dda07329970d1a01e273c37481326fe0c861c8142'

Hachage randomisé

En définissant le paramètre salt les utilisateurs peuvent introduire de l'aléatoire dans la fonction de hachage. Le hachage randomisé est utile pour se protéger des attaques par collisions sur les fonctions de hachage utilisées dans les signatures numériques.

Le hachage aléatoire est conçu pour les situations où une partie, le préparateur du message, génère tout ou partie d'un message à signer par une seconde partie, le signataire du message. Si le préparateur du message est capable de trouver des collisions sur la fonction cryptographique de hachage (c.-à-d. deux messages produisant la même valeur une fois hachés), alors il peut préparer plusieurs versions du message, ayant un sens, qui produiront les mêmes empreintes et même signature mais avec des résultats différents (par exemple transférer 1 000 000 $ sur un compte plutôt que 10 $). Les fonctions cryptographiques de hachage ont été conçues avec comme but premier de résister aux collisions, mais la concentration actuelle d'attaques sur les fonctions de hachage peut avoir pour conséquence qu'une fonction de hachage donnée soit moins résistante qu'attendu. Le hachage aléatoire offre au signataire une protection supplémentaire en réduisant la probabilité que le préparateur puisse générer deux messages ou plus qui renverront la même empreinte lors du processus de génération de la signature — même s'il existe un moyen pratique de trouver des collisions sur la fonction de hachage. Toutefois, l'utilisation du hachage aléatoire peut réduire le niveau de sécurité fourni par une signature numérique si tous les morceaux du message sont préparés par le signataire.

(NIST SP-800-106 "Randomized Hashing for Digital Signatures", article en anglais)

Dans BLAKE2, le sel est passé une seule fois lors de l'initialisation de la fonction de hachage, plutôt qu'à chaque appel de la fonction de hachage.

Avertissement

Salted hashing (ou un hachage simple) avec BLAKE2 ou toute autre fonction de hachage générique, comme SHA-256, ne convient pas pour obscurcir des mots de passe. Voir la FAQ BLAKE2 (page en anglais) pour plus d'informations.

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

Personnalisation

Parfois il est utile de forcer une fonction de hachage à produire différentes empreintes de message d'une même entrée pour différentes utilisations. Pour citer les auteurs de la fonction de hachage Skein :

Nous recommandons que tous les développeurs d'application considèrent sérieusement de faire cela ; nous avons vu de nombreux protocoles où une empreinte était calculée à un endroit du protocole pour être utilisée à un autre endroit car deux calculs d'empreintes étaient réalisés sur des données similaires ou liées, et qu'un attaquant peut forcer une application à prendre en entrée la même empreinte. Personnaliser chaque fonction de hachage utilisée dans le protocole stoppe immédiatement ce genre d'attaque.

(The Skein Hash Function Family, p. 21, article en anglais)

BLAKE2 peut être personnalisé en passant des bytes à l'argument 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'

La personnalisation et le keyed mode peuvent être utilisés ensemble pour dériver différentes clés à partir d'une seule.

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

Mode Arbre

L'exemple ci-dessous présente comment hacher un arbre minimal avec deux nœuds terminaux :

  10
 /  \
00  01

Cet exemple utilise en interne des empreintes de 64 octets, et produit finalement des empreintes 32 octets :

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

Crédits

BLAKE2 a été conçu par Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn, et Christian Winnerlein. Il est basé la version BLAKE qui a participé à la finale de la compétition du NIST SHA-3 créée par Jean-Philippe Aumasson, Luca Henzen, Willi Meier, et Raphael C.-W. Phan.

Il utilise le cœur de l'algorithme de chiffrement de ChaCha conçu par Daniel J. Bernstein.

L'implémentation dans la bibliothèque standard est basée sur le module pyblake2. Elle a été écrite par Dmitry Chestnykh et est basée sur l'implémentation C écrite par Samuel Neves. La documentation a été copiée depuis pyblake2 et écrite par Dmitry Chestnykh.

Le code C a été partiellement réécrit pour Python par Christian Heimes.

Le transfert dans le domaine public s'applique pour l'implémentation C de la fonction de hachage, ses extensions et cette documentation :

Tout en restant dans les limites de la loi, le(s) auteur(s) a (ont) donné tous les droits d’auteur et droits connexes et voisins de ce logiciel au domaine public dans le monde entier. Ce logiciel est distribué sans aucune garantie.

Vous devriez recevoir avec ce logiciel une copie de la licence CC0 Public Domain Dedication. Sinon, voir https://creativecommons.org/publicdomain/zero/1.0/.

Les personnes suivantes ont aidé au développement ou contribué aux modifications du projet et au domaine public selon la licence Creative Commons Public Domain Dedication 1.0 Universal :

  • Alexandr Sokolovskiy

Voir aussi

Module hmac

Un module pour générer des codes d'authentification utilisant des hash.

Module base64

Un autre moyen d'encoder des hash binaires dans des environnements non binaires.

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

La publication FIPS 180-4 sur les algorithmes de hachage sécurisés.

https://csrc.nist.gov/pubs/fips/202/final

La publication FIPS 202 sur le standard SHA-3.

https://www.blake2.net/

Site officiel de BLAKE2.

https://en.wikipedia.org/wiki/Cryptographic_hash_function

Article Wikipedia contenant les informations relatives aux algorithmes ayant des problèmes et leur interprétation au regard de leur utilisation.

https://www.ietf.org/rfc/rfc8018.txt

PKCS #5 : Password-Based Cryptography Specification Version 2.1

https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf

Recommandations du NIST pour la dérivation de clé à partir de mot de passe (ressource en anglais).