hashlib en Python: hashes seguros

Publicado el: 19/08/2026
Tempo de leitura: 5 minutos
Lector de huella digital que representa verificación de hashes con hashlib en Python

El módulo hashlib ofrece una interfaz común para funciones hash criptográficas como SHA-256, SHA-512, SHA-3, SHAKE y BLAKE2. Un hash transforma una cantidad arbitraria de datos en un resumen de tamaño fijo. Un cambio mínimo en la entrada produce un resultado muy diferente, por lo que los hashes son útiles para verificar archivos, identificar contenido, deduplicar datos y construir protocolos criptográficos.

La seguridad depende de elegir la primitiva correcta. SHA-256 puede verificar una descarga, pero no es suficiente para almacenar contraseñas. Un hash sin clave tampoco demuestra quién creó el mensaje. Esta guía cubre las APIs principales, procesamiento incremental, archivos grandes, comparación segura, SHAKE, BLAKE2, PBKDF2 y scrypt.

Cómo funciona un hash

Una función hash recibe bytes y genera un digest. Los mismos bytes producen siempre el mismo resultado. No existe una operación normal de descifrado para recuperar el mensaje, pero las entradas predecibles pueden probarse por fuerza bruta. Por tanto, que sea unidireccional no implica confidencialidad automática.

import hashlib

message = "Academify".encode("utf-8")
hash_object = hashlib.sha256(message)

print(hash_object.digest())
print(hash_object.hexdigest())

digest() devuelve bytes. hexdigest() devuelve texto hexadecimal apropiado para manifests, bases de datos y protocolos textuales. La guía de binascii en Python explica estas representaciones.

Elegir un algoritmo

SHA-256 es una opción habitual e interoperable para integridad. SHA-512 puede ser requerido por un protocolo. SHA-3 utiliza una construcción diferente de SHA-2. BLAKE2 es rápido y admite tamaños configurables y modo con clave. SHAKE produce una salida de longitud variable.

MD5 y SHA-1 tienen debilidades de colisión conocidas. Siguen presentes en formatos heredados e identificadores no adversariales, pero no deben proteger firmas, certificados o contenido controlado por un atacante. El argumento usedforsecurity=False indica un uso no relacionado con seguridad en instalaciones restringidas; no fortalece el algoritmo.

print(sorted(hashlib.algorithms_guaranteed))
print("sha256" in hashlib.algorithms_available)

algorithms_guaranteed contiene los algoritmos portables. algorithms_available puede incluir otros proporcionados por OpenSSL.

Actualizaciones incrementales

No necesitas concatenar ni cargar todo en memoria. Varias llamadas a update() equivalen al hash de todos los bloques concatenados.

hasher = hashlib.sha256()
hasher.update(b"parte uno")
hasher.update(b"parte dos")
print(hasher.hexdigest())

Este patrón es ideal para uploads, sockets y archivos grandes. Sigue la misma estrategia del artículo sobre leer archivos gigantes con Python.

Hash SHA-256 de un archivo

from pathlib import Path
import hashlib

def sha256_file(path: Path, chunk_size: int = 1024 * 1024) -> str:
    hasher = hashlib.sha256()
    with path.open("rb") as file:
        while chunk := file.read(chunk_size):
            hasher.update(chunk)
    return hasher.hexdigest()

print(sha256_file(Path("paquete.zip")))

Compara el resultado con un valor obtenido por un canal autenticado. Si archivo y checksum proceden del mismo servidor comprometido, la comparación no demuestra autenticidad. En distribución de mayor riesgo, usa HTTPS y una firma digital.

Los archivos comprimidos también pueden incluir checksums internos, pero normalmente detectan corrupción accidental. La guía para crear archivos ZIP con Python explica la diferencia.

hashlib.file_digest()

Desde Python 3.11, file_digest() simplifica el hash de un archivo binario y puede utilizar rutas de I/O optimizadas.

with open("paquete.zip", "rb") as file:
    digest = hashlib.file_digest(file, "sha256")

print(digest.hexdigest())

Considera desconocidos la posición y el estado interno del archivo después de la llamada. En Python 3.14, un archivo no bloqueante genera BlockingIOError; versiones anteriores podían añadir bytes nulos al digest por error.

Comparar digests

Una comparación normal suele bastar para un checksum público. Para valores secretos de autenticación utiliza hmac.compare_digest(), que reduce diferencias temporales relacionadas con la primera posición distinta.

import hmac

expected = "a" * 64
calculated = sha256_file(Path("paquete.zip"))

if not hmac.compare_digest(expected, calculated):
    raise ValueError("El digest del archivo no coincide")

Una comparación de tiempo constante no corrige un valor esperado no autenticado ni un protocolo débil.

SHAKE y longitud variable

shake_128 y shake_256 requieren indicar cuántos bytes debe tener el resultado.

identifier = hashlib.shake_256(b"registro-123").hexdigest(20)
print(identifier)

Elige el tamaño según la probabilidad de colisión y el modelo de amenaza. No recortes digests arbitrariamente cuando la entrada pueda ser controlada por terceros.

BLAKE2 y separación de dominios

BLAKE2b está optimizado para sistemas de 64 bits y produce entre 1 y 64 bytes. BLAKE2s produce hasta 32. El argumento person personaliza el hash, separando usos diferentes de una misma entrada.

file_hash = hashlib.blake2b(
    b"contenido",
    digest_size=32,
    person=b"Files-v1",
).hexdigest()

block_hash = hashlib.blake2b(
    b"contenido",
    digest_size=32,
    person=b"Blocks-v1",
).hexdigest()

assert file_hash != block_hash

BLAKE2 también admite modo con clave. Puede autenticar mensajes de forma eficiente, aunque HMAC suele ser preferido cuando importan interoperabilidad y revisión convencional.

Por qué SHA-256 solo no sirve para contraseñas

Los hashes generales están diseñados para ser rápidos. Esto ayuda con archivos, pero permite probar enormes diccionarios de contraseñas. El almacenamiento de credenciales necesita un algoritmo lento, configurable y con salt, como Argon2id, scrypt, bcrypt o PBKDF2.

No copies un ejemplo de verificación de archivos en un sistema de login. Consulta la guía sobre contraseñas y login seguro en Python.

PBKDF2 con salt aleatorio

import os
import hashlib

salt = os.urandom(16)
iterations = 600_000
password = "contraseña larga".encode("utf-8")

derived = hashlib.pbkdf2_hmac(
    "sha256",
    password,
    salt,
    iterations,
)

Almacena algoritmo, iteraciones, salt y valor derivado. Calibra el coste en hardware similar al de producción y limita la longitud de la contraseña antes de la derivación.

scrypt y coste de memoria

hashlib.scrypt() añade un coste de memoria que dificulta ataques paralelos con hardware especializado.

derived = hashlib.scrypt(
    password,
    salt=salt,
    n=2**14,
    r=8,
    p=1,
    dklen=32,
)

Los parámetros deben medirse y guardarse junto al resultado. Maneja errores de memoria y parámetros inválidos de forma explícita; no reduzcas silenciosamente la seguridad.

Identificadores de contenido y caché

Los digests funcionan como identificadores de contenido y claves de caché. Incluye todas las opciones que cambian el resultado y añade una versión para evitar reutilizar entradas antiguas.

def cache_key(url: str, language: str) -> str:
    canonical = f"v1\n{language}\n{url}".encode("utf-8")
    return hashlib.sha256(canonical).hexdigest()

Al trabajar con datos de APIs, define una serialización canónica. La guía para integrar APIs con Python incluye prácticas adicionales de validación y transporte.

Errores frecuentes

Los fallos comunes son pasar str sin codificar, usar MD5 o SHA-1 para seguridad, confundir hash con cifrado, usar SHA-256 puro para contraseñas, comparar tags con ==, confiar en un checksum recibido por el mismo canal inseguro y cargar archivos completos en memoria.

Buenas prácticas

Usa SHA-256 o el algoritmo moderno definido por el protocolo. Procesa datos en bloques. Guarda esquema y versión junto al digest. Separa integridad de autenticidad. Usa HMAC o firmas cuando importa el origen. Para contraseñas, utiliza una KDF lenta con salt. No inventes construcciones criptográficas propias.

Conclusión

hashlib cubre desde hashes de archivos hasta SHA-3, SHAKE, BLAKE2, PBKDF2 y scrypt. La API es sencilla, pero el contexto determina la seguridad. Un digest detecta cambios; un mensaje autenticado necesita clave; una contraseña requiere derivación costosa; y una descarga confiable necesita un valor esperado auténtico.

Consulta la documentación oficial de hashlib y NIST FIPS 180-4.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Sala de servidores iluminada que representa conexiones TLS seguras con ssl en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ssl en Python: conexiones TLS seguras

    Aprende ssl en Python para crear clientes y servidores TLS, validar certificados y hostname, configurar CA, versiones mínimas y mTLS.

    Ler mais

    Tempo de leitura: 5 minutos
    19/08/2026
    Pantalla de verificación de cuenta que representa autenticación de mensajes con HMAC en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    HMAC en Python: autentica mensajes

    Aprende HMAC en Python para firmar y validar webhooks, archivos y mensajes con SHA-256, claves seguras y comparación resistente a

    Ler mais

    Tempo de leitura: 5 minutos
    19/08/2026
    Código binario proyectado que representa conversiones con binascii en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    binascii en Python: binario y ASCII

    Aprende binascii en Python para convertir hexadecimal, Base64 y quoted-printable, calcular CRC y validar datos binarios de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    18/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    codecs en Python: domina encodings

    Aprende codecs en Python para usar encodings, handlers, BOM, streams incrementales y migrar codecs.open a open.

    Ler mais

    Tempo de leitura: 6 minutos
    18/08/2026
    A person reads 'Python for Unix and Linux System Administration' indoors.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    base64 en Python: codifica datos

    Aprende base64 en Python para codificar bytes, usar Base64 URL-safe, validar padding, aplicar límites y diferenciar encoding de cifrado.

    Ler mais

    Tempo de leitura: 5 minutos
    18/08/2026
    Detailed image of a Burmese Python being held. Captured in Toluca, Mexico.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    urllib.parse en Python: maneja URLs

    Aprende urllib.parse en Python para dividir URLs, crear queries, codificar componentes y evitar riesgos con urljoin, redirects, logs y SSRF.

    Ler mais

    Tempo de leitura: 5 minutos
    18/08/2026