hashlib — Hash criptográfico

Propósito:Hashes criptográficos y resúmenes de mensajes

El módulo hashlib define una interfaz de programación para acceder a diferentes algoritmos criptográficos de hash. Para trabajar con un algoritmo específico de hash, usa la función constructora apropiada o new() para crear un objeto hash. A partir de ahí, los objetos utilizan la misma interfaz de programación, sin importar qué algoritmo se esté utilizando.

Algoritmos hash

Como hashlib está «respaldado» por OpenSSL, todos los algoritmos provistos por esa biblioteca están disponibles, incluyendo:

  • md5
  • sha1
  • sha224
  • sha256
  • sha384
  • sha512

Algunos algoritmos están disponibles en todas las plataformas, y algunos dependen de las bibliotecas subyacentes. Para las listas de cada uno, mira algorithms_guaranteed y algorithms_available respectivamente.

hashlib_algorithms.py
import hashlib


print('Guaranteed:\n{}\n'.format(
    ', '.join(sorted(hashlib.algorithms_guaranteed))))
print('Available:\n{}'.format(
    ', '.join(sorted(hashlib.algorithms_available))))
$ python3 hashlib_algorithms.py

Guaranteed:
blake2b, blake2s, md5, sha1, sha224, sha256, sha384, sha3_224,
sha3_256, sha3_384, sha3_512, sha512, shake_128, shake_256

Available:
DSA, DSA-SHA, MD4, MD5, RIPEMD160, SHA, SHA1, SHA224, SHA256,
SHA384, SHA512, blake2b, blake2s, dsaEncryption, dsaWithSHA,
ecdsa-with-SHA1, md4, md5, ripemd160, sha, sha1, sha224, sha256,
sha384, sha3_224, sha3_256, sha3_384, sha3_512, sha512,
shake_128, shake_256, whirlpool

Datos de muestra

Todos los ejemplos en esta sección utilizan los mismos datos de muestra:

hashlib_data.py
import hashlib

lorem = '''Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.'''

Ejemplo MD5

Para calcular el hash MD5, o resumen, para un bloque de datos (aquí un cadena de Unicode convertida en una cadena de bytes), primero crea el objeto hash, luego agrega los datos y llama a digest() o hexdigest().

hashlib_md5.py
import hashlib

from hashlib_data import lorem

h = hashlib.md5()
h.update(lorem.encode('utf-8'))
print(h.hexdigest())

Este ejemplo usa el método hexdigest() en lugar de digest() porque la salida está formateada para que pueda imprimirse claramente. Si un valor del resumen binario es aceptable, usa digest().

$ python3 hashlib_md5.py

3f2fd2c9e25d60fb0fa5d593b802b7a8

Ejemplo SHA1

Un resumen de SHA1 se calcula de la misma manera.

hashlib_sha1.py
import hashlib

from hashlib_data import lorem

h = hashlib.sha1()
h.update(lorem.encode('utf-8'))
print(h.hexdigest())

El valor del resumen es diferente en este ejemplo porque se ha cambiado el algoritmo de MD5 a SHA1.

$ python3 hashlib_sha1.py

ea360b288b3dd178fe2625f55b2959bf1dba6eef

Crear un hash por nombre

A veces es más conveniente referirse al algoritmo por su nombre en una cadena en lugar de utilizar la función constructora directamente. Es útil, por ejemplo, para poder almacenar el tipo de hash en un archivo de configuración. En esos casos, usa new() para crear un hash calculadora.

hashlib_new.py
import argparse
import hashlib
import sys

from hashlib_data import lorem


parser = argparse.ArgumentParser('hashlib demo')
parser.add_argument(
    'hash_name',
    choices=hashlib.algorithms_available,
    help='the name of the hash algorithm to use',
)
parser.add_argument(
    'data',
    nargs='?',
    default=lorem,
    help='the input data to hash, defaults to lorem ipsum',
)
args = parser.parse_args()

h = hashlib.new(args.hash_name)
h.update(args.data.encode('utf-8'))
print(h.hexdigest())

Cuando se ejecuta con una variedad de argumentos:

$ python3 hashlib_new.py sha1

ea360b288b3dd178fe2625f55b2959bf1dba6eef

$ python3 hashlib_new.py sha256

3c887cc71c67949df29568119cc646f46b9cd2c2b39d456065646bc2fc09ffd8

$ python3 hashlib_new.py sha512

a7e53384eb9bb4251a19571450465d51809e0b7046101b87c4faef96b9bc904cf7f90
035f444952dfd9f6084eeee2457433f3ade614712f42f80960b2fca43ff

$ python3 hashlib_new.py md5

3f2fd2c9e25d60fb0fa5d593b802b7a8

Actualizaciones incrementales

El método update() de las calculadoras hash puede ser llamado repetidamente. Cada vez, el resumen se actualiza en base al texto adicional ingresado. La actualización incremental es más eficiente que leer un archivo completo en memoria, y produce los mismos resultados.

hashlib_update.py
import hashlib

from hashlib_data import lorem

h = hashlib.md5()
h.update(lorem.encode('utf-8'))
all_at_once = h.hexdigest()


def chunkize(size, text):
    "Return parts of the text in size-based increments."
    start = 0
    while start < len(text):
        chunk = text[start:start + size]
        yield chunk
        start += size
    return


h = hashlib.md5()
for chunk in chunkize(64, lorem.encode('utf-8')):
    h.update(chunk)
line_by_line = h.hexdigest()

print('All at once :', all_at_once)
print('Line by line:', line_by_line)
print('Same        :', (all_at_once == line_by_line))

Este ejemplo muestra cómo actualizar un resumen de forma incremental a medida que datos son leídos o producidos de otra manera.

$ python3 hashlib_update.py

All at once : 3f2fd2c9e25d60fb0fa5d593b802b7a8
Line by line: 3f2fd2c9e25d60fb0fa5d593b802b7a8
Same        : True

Ver también