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

**Code source :** Lib/hashlib.py

======================================================================

This module implements a common interface to many different hash
algorithms. Included are the FIPS secure hash algorithms SHA224,
SHA256, SHA384, SHA512, (defined in the FIPS 180-4 standard), the
SHA-3 series (defined in the FIPS 202 standard) as well as the legacy
algorithms SHA1 (formerly part of FIPS) and the MD5 algorithm (defined
in internet **RFC 1321**).

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* must be a file-like object opened for reading in binary
   mode. It accepts file objects from  builtin "open()", "BytesIO"
   instances, SocketIO objects from "socket.socket.makefile()", and
   similar. *fileobj* must be opened in blocking mode, otherwise a
   "BlockingIOError" may be raised.

   The function may bypass Python's I/O and use the file descriptor
   from "fileno()" directly. *fileobj* must be assumed to be in an
   unknown state after this function returns or raises. It is up to
   the caller to close *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("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

   Ajouté dans la version 3.11.

   Modifié dans la version 3.13.4: Now raises a "BlockingIOError" if
   the file is opened in blocking mode. Previously, spurious null
   bytes were added to the digest.


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

   [image: Explication des paramètres du mode arbre.][image]

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/nistspecialpublication8
  00-132.pdf
     Recommandations du NIST pour la dérivation de clé à partir de mot
     de passe (ressource en anglais).
