"hashlib" --- Hashes seguros y resúmenes de mensajes
****************************************************

**Código fuente:** Lib/hashlib.py

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

Este módulo implementa una interfaz común a diferentes algoritmos de
hash y resúmenes de mensajes seguros. Están incluidos los algoritmos
de hash FIPS seguros SHA1, SHA224, SHA226, SHA384 y SHA512 (definidos
en FIPS 180-2) además del algoritmo MD5 de RSA (definido en Internet
**RFC 1321**). Los términos "hash seguro" y "resumen de mensaje" son
intercambiables. Los algoritmos más antiguos fueron denominados
resúmenes de mensajes. El término moderno es hash seguro.

Nota:

  Si quieres las funciones de hash adler32 o crc32, están disponibles
  en el módulo "zlib".

Advertencia:

  Algunos algoritmos tienen conocidas debilidades de colisión de hash,
  consulte la sección "Ver también" al final.


Algoritmos de hash
==================

Hay un método constructor nombrado para cada tipo de *hash*. Todos
retornan un objeto de hash con la misma interfaz simple. Por ejemplo,
usa "sha256()" para crear un objeto de hash SHA-256. Ahora puedes
alimentar este objeto con *objetos como bytes* (normalmente "bytes")
usando el método "update()". En cualquier punto puedes pedir el
resumen (*digest*) de la concatenación de los datos alimentados al
mismo usando los métodos "digest()" o "hexdigest()".

Nota:

  Para un rendimiento multihilo mejor, el *GIL* de Python es liberado
  para datos superiores a 2047 bytes en la creación o actualización de
  objetos.

Nota:

  La alimentación de objetos de cadenas en "update()" no está
  soportada, ya que los hashes funcionan en bytes, no en caracteres.

Los constructores para algoritmos de hash siempre presentes en este
módulo son "sha1()", "sha224()", "sha256()", "sha384()", "sha512()",
"blake2b()" y "blake2s()". "md5()" también está disponible
normalmente, aunque puede faltar si estás usando una construcción de
Python que cumple de forma rara con los requisitos FIPS. Algoritmos
adicionales también pueden estar disponibles dependiendo de la
biblioteca OpenSSL que Python usa en tu plataforma. En la mayoría de
plataformas las funciones "sha3_224()", "sha3_256()", "sha3_384()",
"sha3_512()", "shake_128()" y "shake_256()" también están disponibles.

Nuevo en la versión 3.6: Constructores SHA3 (Keccak) y SHAKE
"sha3_224()", "sha3_256()", "sha3_384()", "sha3_512()", "shake_128()",
"shake_256()".

Nuevo en la versión 3.6: Fueron añadidas "blake2b()" y "blake2s()".

Por ejemplo, para obtener el resumen de la cadena de bytes "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.digest_size
   32
   >>> m.block_size
   64

Más resumido:

>>> hashlib.sha224(b"Nobody inspects the spammish repetition").hexdigest()
'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'

hashlib.new(name[, data])

   Es un constructor genérico que toma la cadena *name* del algoritmo
   deseado como su primer parámetro. También existe para permitir
   acceso a los hashes arriba listados así como cualquiera de los
   otros algoritmos que tu biblioteca OpenSSL puede ofrecer. Los
   constructores nombrados son mucho más rápidos que "new()" y
   deberían preferirse.

Usando "new()" con un algoritmo provisto por OpenSSL:

>>> h = hashlib.new('sha512_256')
>>> h.update(b"Nobody inspects the spammish repetition")
>>> h.hexdigest()
'19197dc4d03829df858011c6c87600f994a858103bbc19005f20987aa19a97e2'

Hashlib provee los siguientes atributos constantes:

hashlib.algorithms_guaranteed

   Un conjunto que contiene los nombres de los algoritmos garantizados
   a ser soportados por este módulo en todas las plataformas. Ten en
   cuenta que 'md5' se encuentra en esta lista a pesar de que algunos
   proveedores ofrecen una extraña construcción Python "compatible con
   FIPS" que la excluye.

   Nuevo en la versión 3.2.

hashlib.algorithms_available

   Un conjunto que contiene los nombres de los algoritmos de hash que
   están disponibles en el intérprete de Python en ejecución. Estos
   nombres serán reconocidos cuando sean pasados a "new()".
   "algorithms_guaranteed" siempre será un subconjunto. El mismo
   algoritmo puede aparecer múltiples veces en este conjunto bajo
   diferentes nombres (gracias a OpenSSL).

   Nuevo en la versión 3.2.

Los siguientes valores son provistos como atributos constantes de los
objetos hash retornados por los constructores:

hash.digest_size

   El tamaño del hash resultante en bytes.

hash.block_size

   El tamaño del bloque interno del algoritmo de hash en bytes.

Un objeto hash tiene los siguientes atributos:

hash.name

   El nombre canónico de este hash, siempre en minúsculas y siempre
   adecuado como un parámetro a "new()" para crear otro hash de este
   tipo.

   Distinto en la versión 3.4: El atributo *name* ha estado presente
   en CPython desde su inicio, pero desde Python 3.4 no fue
   especificado formalmente, por lo que puede no existir en algunas
   plataformas.

Un objeto hash tiene los siguientes métodos:

hash.update(data)

   Actualiza el objeto de hash con el *bytes-like object*.
   Invocaciones repetidas son equivalentes a una única invocación con
   la concatenación de todos los argumentos: "m.update(a);
   m.update(b)" es equivalente a "m.update(a+b)".

   Distinto en la versión 3.1: El GIL de Python es liberado para
   permitir a otros hilos ejecutarse mientras ocurren actualizaciones
   de hash en datos con tamaños superiores a 2047 bytes cuando se usan
   algoritmos de hash suministrados por OpenSSL.

hash.digest()

   Retorna el resumen de los datos pasados al método "update()" hasta
   el momento. Este es un objeto de bytes de tamaño "digest_size" el
   cual puede contener bytes en el rango completo desde 0 a 255.

hash.hexdigest()

   Como "digest()" excepto que el resumen es retornado como un objeto
   de cadena del doble de largo, conteniendo sólo dígitos
   hexadecimales. Este puede ser usado para intercambiar el valor de
   forma segura en correos electrónicos u otros entornos no binarios.

hash.copy()

   Retorna una copia ("clon") del objeto hash. Este puede ser usado
   para calcular eficientemente los resúmenes de datos compartiendo
   una subcadena inicial común.


Resúmenes SHAKE de largo variable
=================================

Los algoritmos "shake_128()" y "shake_256()" proveen resúmenes de
largo variable con largo_en_bits//2 hasta 128 ó 256 bits de seguridad.
Como tales, sus métodos de resumen requieren un largo. El largo máximo
no está limitado por el algoritmo SHAKE.

shake.digest(length)

   Retorna el resumen de los datos pasados al método "update()" hasta
   el momento. Este es un objeto de bytes de tamaño *length* el cual
   puede contener bytes en el rango completo desde 0 a 255.

shake.hexdigest(length)

   Como "digest()" excepto que el resumen es retornado como un objeto
   de cadena del doble de largo, conteniendo sólo dígitos
   hexadecimales. Este puede ser usado para intercambiar el valor de
   forma segura en correos electrónicos u otros entornos no binarios.


Derivación de clave
===================

Los algoritmos de derivación de clave y estiramiento de clave están
diseñados para el cifrado seguro de contraseña. Algoritmos ingenuos
como "sha1(password)" no son resistentes contra ataques de fuerza
bruta. Una buena función hash de contraseña debe ser afinable, lenta e
incluir una sal.

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

   La función provee contraseñas PKCS#5 basadas en función de
   derivación de clave 2. Usa HMAC como función de pseudoaleatoriedad.

   La cadena *hash_name* es el nombre deseado del algoritmo de resumen
   de hash para HMAC, ej. 'sha1' o 'sha256'. *password* y *salt* son
   interpretados como búferes de bytes. Aplicaciones y bibliotecas
   deberían limitar *password* a un largo razonable (ej. 1024). *salt*
   debería ser sobre 16 o más bytes desde una fuente adecuada, ej.
   "os.urandom()".

   El número de *iterations* debería ser elegido basado en el
   algoritmo de hash y el poder de cómputo. A partir del 2013, se
   sugiere al menos 100,000 iteraciones de SHA-256.

   *dklen* es el largo de la clave derivada. Si *dklen* es "None"
   entonces el tamaño de resumen del algoritmo de hash *hash_name* es
   usado, ej. 64 para SHA-512.

   >>> import hashlib
   >>> dk = hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 100000)
   >>> dk.hex()
   '0394a2ede332c9a13eb82e9b24631604c31df978b4e2f0fbd2c549944f9d79a5'

   Nuevo en la versión 3.4.

   Nota:

     Una implementación rápida de *pbkdf2_hmac* está disponible con
     OpenSSL. La implementación Python usa una versión en línea de
     "hmac". Es aproximadamente tres veces más lenta y no libera el
     GIL.

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

   La función provee una contraseña scrypt basada en una función
   derivación de clave como es definida en **RFC 7914**.

   *password* y *salt* deben ser *objetos de bytes*. Aplicaciones y
   bibliotecas deberían limitar *password* a un largo razonable (ej.
   1024). *salt* debería ser aproximadamente 16 o más bytes de una
   fuente adecuada, ej. "os.unrandom()".

   *n* es el factor de coste de CPU/Memoria, *r* el tamaño de bloque,
   *p* el factor de paralelización y *maxmem* limita la memoria
   (OpenSSL 1.1.0 por defecto a 32 MiB). *dklen* es el largo de la
   clave derivada.

   Disponibilidad: OpenSSL 1.1+.

   Nuevo en la versión 3.6.


BLAKE2
======

BLAKE2 es una función de hash criptográfico definida en **RFC 7693**
que viene en dos sabores:

* **BLAKE2b**, optimizada para plataformas de 64 bits y produce
  resúmenes de cualquier tamaño entre 1 y 64 bytes,

* **BLAKE2s**, optimizada para plataformas de 8 a 32 bits y produce
  resúmenes de cualquier tamaño entre 1 y 32 bytes.

BLAKE2 proporciona el **modo keyed** (un remplazamiento más simple
rápido para HMAC), **cifrado salado** (*salted hashing*),
**personalización** y **cifrado de árbol**.

Los objetos hash de este módulo siguen los estándares de los objetos
de la biblioteca "hashlib".


Creando objetos hash
--------------------

Se crean nuevos objetos hash invocando a las funciones de constructor:

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)

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)

Estas funciones retornan los objetos hash correspondientes para
calcular BLAKE2b o BLAKE2s. Ellas toman opcionalmente estos parámetros
generales:

* *data*: trozo inicial de datos a cifrar, el cual debe ser un *bytes-
  like object*. Puede ser pasado sólo como argumento posicional.

* *digest_size*: tamaño del resumen de salida en bytes.

* *key*: clave para el cifrado de clave (*keyed hashing*) (hasta 64
  bytes para BLAKE2b, hasta 32 bytes para BLAKE2s).

* *salt*: sal para el cifrado aleatorio (hasta 16 bytes para BLAKE2b,
  hasta 8 bytes para BLAKE2s).

* *person*: cadena de personalización (hasta 16 bytes para BLAKE2b,
  hasta 8 bytes para BLAKE2s).

La siguiente tabla muestra los límites para parámetros generales (en
bytes):

+---------+-------------+----------+-----------+-------------+
| Cifrado | digest_size | len(key) | len(salt) | len(person) |
|=========|=============|==========|===========|=============|
| BLAKE2b | 64          | 64       | 16        | 16          |
+---------+-------------+----------+-----------+-------------+
| BLAKE2s | 32          | 32       | 8         | 8           |
+---------+-------------+----------+-----------+-------------+

Nota:

  La especificación BLAKE2 define largos constantes para los
  parámetros de sal y personalización, sin embargo, por conveniencia,
  esta implementación acepta cadenas de bytes de cualquier tamaño
  hasta el largo especificado. Si el largo del parámetro es menor que
  el especificado, es acolchado con ceros, por lo tanto, por ejemplo,
  "b'salt'" y "b'salt\x00'" es el mismo valor. (Este no es el caso
  para *key*.)

Estos tamaños están disponibles como constantes del módulo descritas
abajo.

Las funciones constructoras también aceptan los siguientes parámetros
de cifrado de árbol:

* *fanout*: despliegue en abanico (0 a 255, 0 si ilimitado, 1 en modo
  secuencial).

* *depth*: profundidad máxima del árbol (1 a 255, 255 si ilimitado, 1
  en modo secuencial).

* *leaf_size*: tamaño máximo en bytes de hoja (0 a 2**32-1, 0 si
  ilimitado o en modo secuencial).

* *node_offset*: desplazamiento del nodo (0 a 2**64-1 para BLAKE2b, 0
  a 2**48 para BLAKE2s, 0 para la primera, la hoja más a la izquierda
  o en modo secuencial).

* *node_depth*: profundidad de nodo (0 a 255, 0 para hojas o en modo
  secuencial).

* *inner_size*: tamaño interno del resumen (0 a 64 para BLAKE2b, 0 a
  32 para BLAKE2s, 0 en modo secuencial).

* *last_node*: booleano indicando si el nodo procesado es el último
  (*False* para modo secuencial).

   [imagen: Explanation of tree mode parameters.][imagen]

Consulta la sección 2.10 en la *especificación BLAKE2
<https://blake2.net/blake2_20130129.pdf>* para una revisión integral
del cifrado en árbol.


Constantes
----------

blake2b.SALT_SIZE

blake2s.SALT_SIZE

Largo de sal (largo máximo aceptado por los constructores).

blake2b.PERSON_SIZE

blake2s.PERSON_SIZE

Largo de cadena de personalización (largo máximo aceptado por los
constructores).

blake2b.MAX_KEY_SIZE

blake2s.MAX_KEY_SIZE

Tamaño máximo de clave.

blake2b.MAX_DIGEST_SIZE

blake2s.MAX_DIGEST_SIZE

Tamaño máximo de resumen que puede producir la función hash.


Ejemplos
--------


Cifrado simple
~~~~~~~~~~~~~~

Para calcular el hash de algunos datos, primero debes construir un
objeto hash invocando a la función del constructor apropiada
("blake2b()" o "blake2s()"), entonces actualizarlo con los datos
invocando "update()" en el objeto y, finalmente, obtener el resumen
del objeto invocando "digest()" (o "hexdigest()" para una cadena
codificada en hexadecimal).

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

Como atajo, puedes pasar el primer trozo de datos para actualizar
directamente el constructor como el argumento posicional:

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

Puedes invocar "hash.update()" tantas veces como necesites para
actualizar el hash iterativamente:

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


Usar diferentes tamaños de resumen
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

BLAKE2 tiene tamaño de resúmenes configurables de hasta 64 bytes para
BLAKE2b y 32 bytes para BLAKE2s. Por ejemplo, para remplazar SHA-1 con
BLAKE2b sin cambiar el tamaño de la salida, puedes decirle a BLAKE2b
que produzca resúmenes de 20 bytes:

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

Objetos hash con diferentes tamaños de resumen tienen salidas
completamente diferentes (hashes más cortos *no* son prefijos de
hashes más largos); BLAKE2b y BLAKE2s producen salidas diferentes
incluso si el largo de salida es el mismo:

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


Cifrado de clave
~~~~~~~~~~~~~~~~

El cifrado de clave puede ser usado para autentificación como remplazo
más rápido y simple para Código de autentificación de mensajes en
clave-hash (HMAC). BLAKE2 puede ser usado de forma segura en modo de
prefijo MAC gracias a la propiedad de indiferenciabilidad heredada de
BLAKE.

Este ejemplo muestra como obtener un código de autentificación
(codificado como hexadecimal) de 128 bits para el mensaje "b'message
data'" con la clave "b'pseudorandom key'":

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

Como ejemplo práctico, una aplicación web puede firmar simétricamente
cookies enviadas a los usuarios y verificarlas más tarde para asegurar
que no fueron manipuladas con:

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

Incluso aunque hay un modo de cifrado de claves nativo, BLAKE2 puede,
por supuesto, ser usado en construcción de HMAC con el módulo "hmac":

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


Cifrado aleatorio
~~~~~~~~~~~~~~~~~

Definiendo el parámetro *salt* los usuarios pueden introducir
aleatoriedad a la función hash. El cifrado aleatorio es útil para
proteger contra ataques de colisión en la función hash usada en firmas
digitales.

   El cifrado aleatorio está diseñado para situaciones en las que una
   parte, el preparador del mensaje, genera todo o parte de un mensaje
   para ser firmado por una segunda parte, el firmante del mensaje. Si
   el preparador del mensaje es capaz de encontrar colisiones de
   funciones hash criptográficas (ej., dos mensajes produciendo el
   mismo valor de hash), entonces ellos pueden preparar versiones
   significativas del mensaje que producirían el mismo valor de hash y
   firma digital, pero con diferentes resultados (ej., transfiriendo
   1,000,000 $ a una cuenta, en lugar de 10 $), Las funciones de hash
   criptográfico han sido diseñadas con resistencia de colisión como
   objetivo principal, pero la concentración actual en el ataque a las
   funciones hash criptográficas puede resultar en una función hash
   criptográfica dada que provea menor resistencia de colisión de la
   esperada. El cifrado aleatorio ofrece al firmante protección
   adicional reduciendo la probabilidad de que un preparador puede
   generar dos o más mensajes que en última instancia producen el
   mismo valor hash durante el proceso de generación de la firma
   digital, --- incluso si es práctico encontrar colisiones para la
   función hash. Sin embargo, el uso de cifrado aleatorio puede
   reducir la cantidad de seguridad provista por una firma digital
   cuando todas las porciones del mensaje son preparadas por el
   firmante.

   (NIST SP-800-106 "Randomized Hashing for Digital Signatures")

En BLAKE2 la sal es procesada como una entrada de una vez a la función
hash durante la inicialización, en lugar de como una entrada para cada
función de compresión.

Advertencia:

  El *cifrado salado* (o sólo cifrado) con BLAKE2 o cualquier otra
  función de hash criptográfico de propósito general, como SHA-256, no
  son aptas para cifrar contraseñas. Ver BLAKE2 FAQ para más
  información.

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


Personalización
~~~~~~~~~~~~~~~

A veces es útil forzar a la función hash para producir diferentes
resúmenes para la misma entrada para diferentes propósitos. Citando a
los autores de la función hash Skein:

   Recomendamos que todos los diseñadores de aplicaciones consideren
   seriamente hacer esto; hemos visto muchos protocolos donde un hash
   que es calculado en una parte del protocolo puede ser usado en una
   parte completamente diferente porque dos cálculos hash fueron
   realizados en datos similares o relacionados, y el atacante puede
   forzar a la aplicación a hacer las entradas hash iguales.
   Personalizar cada función hash usada en el protocolo resumidamente
   detiene este tipo de ataque.

   (The Skein Hash Function Family, p. 21)

BLAKE2 puede ser personalizado pasando bytes al argumento *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'

Se puede usar también personalización en conjunto con el modo de clave
para derivar diferentes claves desde una sola.

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


Modo de árbol
~~~~~~~~~~~~~

Aquí hay un ejemplo de cifrar un árbol mínimo con dos nodos de hoja:

     10
    /  \
   00  01

Este ejemplo usa resúmenes internos de 64 bytes, y retorna el resumen
final de 32 bytes:

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

BLAKE2 fue diseñado por *Jean-Philippe Aumasson*, *Samuel Neves*,
*Zooko Wilcox-O'Hearn* y *Christian Winnerlein* basado en el SHA-3
finalista BLAKE creado por *Jean-Philippe Aumasson*, *Luca Henzen*,
*Willi Meier* y *Raphael C.-W. Phan*.

Usa el algoritmo núcleo del cifrado ChaCha diseñado por *Daniel J.
Bernstein*.

La implementación stdlib está basada en el módulo pyblake2. Fue
escrita por *Dmitry Chestnykh* basada en la implementación C escrita
por *Samuel Neves*. La documentación fue copiada desde pyblake2 y
escrita por *Dmitry Chestnykh*.

El código C fue parcialmente reescrito para Python por *Christian
Heimes*.

La siguiente dedicación de dominio público aplica tanto para la
implementación de la función hash C, el código de extensión y su
documentación:

   En la medida en que la ley lo permite, el/los autor/es han dedicado
   todos los derechos de autor y los derechos relacionados y vecinos
   de este software al dominio público mundial. Este software se
   distribuye sin ninguna garantía.

   Deberías haber recibido una copia de la Dedicación CC0 de Dominio
   Público junto a este software. Si no, consulta
   https://creativecommons.org/publicdomain/zero/1.0/.

Las siguientes personas han ayudado con el desarrollo o contribuyeron
con sus cambios al proyecto y el dominio público de acuerdo a Creative
Commons Public Domain Dedication 1.0 Universal:

* *Alexandr Sokolovskiy*

Ver también:

  Módulo "hmac"
     Un módulo para generar mensajes de códigos de autentificación
     usando hashes.

  Módulo "base64"
     Otra forma de codificar hashes binarios para entornos no
     binarios.

  https://blake2.net
     Sitio web oficial de BLAKE2.

  https://csrc.nist.gov/csrc/media/publications/fips/180/2/archive/20
  02-08-01/documents/fips180-2.pdf
     La publicación FIPS 180-2 sobre Algoritmos de Cifrado Seguros.

  https://en.wikipedia.org/wiki/Cryptographic_hash_function#Cryptogra
  phic_hash_algorithms
     Artículo de Wikipedia con información sobre cuáles algoritmos
     tienen errores conocidos y lo que eso significa con respecto a su
     uso.

  https://www.ietf.org/rfc/rfc2898.txt
     PKCS #5: Password-Based Cryptography Specification Version 2.0
