Saltar al contenido
AldeaCode Logo
Generador de Hashes / Python Desarrollador 100% local

Hashes de strings en Python: hashlib, encoding y la trampa de las contraseñas

Python trae `hashlib` en la stdlib y eso, honestamente, es todo lo que necesitas para checksums, content-addressed storage o ETags. El error que comete todo el mundo la primera vez es olvidar que `hashlib` quiere bytes, no strings.

hashlib es la respuesta de la stdlib

hashlib está integrado desde siempre y expone SHA-1, SHA-256, SHA-384, SHA-512, la familia SHA-3, BLAKE2 y el MD5 legacy. La API es la misma en todos los algoritmos:

```py import hashlib

digest = hashlib.sha256(b"AldeaCode").hexdigest() ```

El constructor recibe bytes. Si le pasas un str te suelta TypeError: Strings must be encoded before hashing. La solución es una llamada a .encode("utf-8"). Sé siempre explícito con el encoding. Los defaults varían entre plataformas y no quieres un mismatch de hash Mac vs Windows porque alguien metió una vocal acentuada.

El encoding es parte del contrato

Dos strings que parecen idénticos pueden producir hashes diferentes si sus bytes subyacentes difieren. El caso clásico es Unicode compuesto vs descompuesto: "café" puede ser U+00E9 o U+0065 U+0301. Se renderizan igual. Hashean distinto.

Si estás hasheando entrada de usuario que puede venir de plataformas distintas, normaliza primero:

```py import unicodedata, hashlib

def stable_sha256(text: str) -> str: normalized = unicodedata.normalize("NFC", text) return hashlib.sha256(normalized.encode("utf-8")).hexdigest() ```

Suena pedante hasta que ves dos registros en tu base de datos que deberían coincidir por hash de contenido y no coinciden.

hmac es para hashes con clave

Si necesitas verificar que un mensaje lo produjo alguien que conoce un secreto compartido (firmas de webhook, firma de peticiones a APIs, verificación JWT-HS256), no concatenes secret + payload y hashes eso. Usa hmac de la stdlib.

```py import hmac, hashlib

signature = hmac.new( key=secret.encode("utf-8"), msg=payload.encode("utf-8"), digestmod=hashlib.sha256, ).hexdigest() ```

Usa hmac.compare_digest (tiempo constante) para verificar, nunca ==, para evitar ataques de timing. La documentación de Python lo señala explícitamente.

bcrypt o argon2 para contraseñas

hashlib.sha256 no es un hash de contraseñas. Es demasiado rápido. Una GPU de consumo prueba miles de millones de candidatos SHA-256 por segundo, así que una contraseña de 10 caracteres se rompe por fuerza bruta en horas.

Para contraseñas instala argon2-cffi o bcrypt:

```py from argon2 import PasswordHasher

ph = PasswordHasher() hashed = ph.hash("correct horse battery staple") ph.verify(hashed, "correct horse battery staple") ```

Argon2id es la recomendación por defecto de OWASP desde 2021. bcrypt vale si ya tienes un schema. SHA pelado nunca.

Ejemplo completo

python
import hashlib
import hmac
import unicodedata

# Hash estable de texto arbitrario
text = "AldeaCode"
normalized = unicodedata.normalize("NFC", text)
sha256 = hashlib.sha256(normalized.encode("utf-8")).hexdigest()
print(sha256)

# Verificación de firma de webhook
secret = b"shared-secret"
payload = b'{"event":"deploy"}'
signature = hmac.new(secret, payload, hashlib.sha256).hexdigest()
print(signature)

¿Solo necesitas el resultado?

Cuando solo quieres hashear un string puntual fuera de un pipeline, tipo verificar el checksum de una release o ver qué devuelve `sha256("hello")`, abrir una shell de Python son demasiados pasos. Pega el valor en el generador de hashes del navegador y lee las cuatro variantes SHA a la vez, sin instalar nada.

Abrir Generador de Hashes SHA →

Preguntas frecuentes

¿Por qué hashlib rechaza mi string?

hashlib solo acepta bytes. Llama a .encode('utf-8') en el string primero. Especifica siempre el encoding para que el hash sea reproducible entre plataformas.

¿hashlib.sha256 es thread-safe?

El constructor sí. El objeto hash devuelto no. Si dos threads hashean entradas distintas, dale a cada uno su propia instancia hashlib.sha256() en lugar de compartir una y llamar a update.

¿Debería usar hashlib.sha3_256 en lugar de hashlib.sha256?

Para aplicaciones nuevas las dos valen. SHA-3 tiene otra construcción interna (Keccak) y no es vulnerable a length-extension, lo cual importa solo en esquemas tipo HMAC artesanal. SHA-256 es más rápido en la mayoría del hardware.