Hashing, cifrado y codificación:
tres cosas que la gente confunde a diario
Fundamentos de criptografía | unfantasmaenelsistema.com
«La contraseña se guarda encriptada». «He encriptado el archivo en Base64». «El hash sirve para cifrar los datos». Estas tres frases se oyen a diario en oficinas, foros y hasta en notas de prensa de empresas que acaban de sufrir una brecha, y las tres mezclan conceptos que no tienen nada que ver. Hashing, cifrado y codificación resuelven problemas distintos, se comportan de forma distinta y fallan de forma distinta. Confundirlos no es una cuestión de purismo: lleva a decisiones concretas que dejan datos al descubierto.
Este artículo aclara los tres de una vez, con ejemplos cotidianos y sin matemáticas. Al terminar sabrás por qué una contraseña bien guardada no se puede «desencriptar», por qué Base64 no oculta absolutamente nada, y por qué usar SHA-256 «a secas» para guardar contraseñas sigue siendo un error aunque SHA-256 sea un algoritmo excelente para otras cosas.
Qué aprenderás en este artículo
Qué es una función hash y qué propiedades la hacen útil (y cuáles se rompieron en MD5 y SHA-1) · Por qué el hash de contraseñas (bcrypt, scrypt, Argon2) es una categoría aparte con sal y coste · La diferencia real entre cifrar (reversible, con clave) y codificar (reversible, sin secreto) · Para qué sirve cada mecanismo y cuándo NO usarlo · Los tres errores más repetidos: Base64 «para ocultar», hashear sin sal y SHA-256 a pelo para claves
1. Codificación: cambiar de formato, no de secreto
Codificar es transformar datos de una representación a otra siguiendo una regla pública y conocida. No hay clave, no hay secreto y no hay intención de proteger nada: el único objetivo es que la información sobreviva a un canal que, de otro modo, la estropearía.
- Base64 convierte datos binarios (una imagen, un adjunto) en texto ASCII para poder meterlos en un correo, un JSON o una URL sin que se corrompan
- Hexadecimal representa cada byte como dos caracteres del 0 al F; se usa para mostrar hashes, claves o volcados de memoria de forma legible
- URL encoding (percent-encoding) sustituye caracteres conflictivos en una dirección web: un espacio pasa a %20
- ASCII, UTF-8 son codificaciones que asignan números a los caracteres de texto
Lo esencial: cualquiera puede deshacer una codificación, porque la regla es pública y no interviene ningún secreto. Descodificar Base64 es una operación de una línea en cualquier lenguaje, navegador o web. Por eso decir «lo he protegido con Base64» es como decir que has escondido una carta escribiéndola en mayúsculas.
# Base64 NO es cifrado: se deshace sin ninguna clave $ echo -n 'clave-secreta-123' | base64 Y2xhdmUtc2VjcmV0YS0xMjM= $ echo -n 'Y2xhdmUtc2VjcmV0YS0xMjM=' | base64 -d clave-secreta-123
2. Hashing: una huella de un solo sentido
Una función hash criptográfica coge una entrada de cualquier tamaño (una palabra, un fichero de 4 GB) y devuelve una cadena de longitud fija, su resumen o digest. La misma entrada produce siempre el mismo resumen; un cambio de un solo bit en la entrada produce un resumen completamente distinto.
Lo que la hace criptográficamente útil son tres propiedades:
- Unidireccionalidad (resistencia a preimagen): dado un resumen, no hay forma práctica de reconstruir la entrada que lo generó salvo probando candidatos uno a uno
- Resistencia a segunda preimagen: dada una entrada, no se puede encontrar otra distinta con el mismo resumen
- Resistencia a colisiones: no se pueden encontrar dos entradas cualesquiera que compartan resumen
El hash no tiene clave y no es reversible por diseño: no es que «todavía no sepamos descifrarlo», es que la operación descarta información y no existe la vuelta atrás. Se usa para verificar integridad (¿este fichero descargado es idéntico al original?), para firmar documentos (se firma el hash, no el documento entero) y para indexar datos.
2.1 MD5 y SHA-1 están rotos; SHA-256 y sucesores, no
«Roto» aquí significa que la resistencia a colisiones ha caído: se pueden fabricar dos ficheros distintos con el mismo resumen. MD5 cayó en la práctica hacia 2005 y SHA-1 recibió una colisión real y pública en 2017 (el ataque SHAttered de Google). Ninguno de los dos debe usarse ya para nada que dependa de la seguridad, aunque siguen sirviendo como suma de comprobación no adversarial (detectar corrupción accidental de un disco, por ejemplo).
| Función | Tamaño del resumen | Estado | Uso recomendado hoy |
|---|---|---|---|
| MD5 | 128 bits | Roto (colisiones triviales) | Solo checksums no adversariales |
| SHA-1 | 160 bits | Roto (colisión pública 2017) | Nada nuevo; migrar lo que quede |
| SHA-256 / SHA-512 | 256 / 512 bits | Sólido | Integridad, firmas, propósito general |
| SHA-3 (Keccak) | configurable | Sólido, diseño distinto a SHA-2 | Alternativa a SHA-2 |
| BLAKE2 / BLAKE3 | configurable | Sólido y muy rápido | Integridad de gran volumen |
Un hash rápido es una virtud… salvo para contraseñas
SHA-256 está diseñado para ser veloz: una CPU moderna calcula cientos de millones por segundo y una GPU, muchos miles de millones. Eso es perfecto para verificar la integridad de una descarga y catastrófico para proteger contraseñas, porque un atacante con la base de datos robada puede probar esos mismos miles de millones de candidatos por segundo
3. Hash de contraseñas: una categoría aparte
Guardar contraseñas es un caso especial. No queremos poder recuperarlas (por eso no se cifran: se hashean), pero tampoco nos vale un hash de propósito general, precisamente porque es demasiado rápido. La solución tiene dos ingredientes: sal y coste.
3.1 La sal
La sal es un valor aleatorio único que se genera para cada contraseña y se guarda junto al hash (no es secreto). Se combina con la contraseña antes de hashear. Con sal:
- Dos usuarios con la misma contraseña tienen hashes distintos, así que no se ve «quién comparte clave» en el volcado
- Las rainbow tables (tablas precalculadas de hash -> contraseña) dejan de servir, porque habría que precalcular una tabla por cada sal posible
- El atacante se ve forzado a atacar cada contraseña por separado, no todas a la vez
3.2 El coste (factor de trabajo)
Los algoritmos de hash de contraseñas son deliberadamente lentos y ajustables. Tienen un parámetro que multiplica el trabajo necesario: más iteraciones, más memoria, más paralelismo. Se calibra para que verificar un login legítimo tarde una fracción de segundo en tu servidor, lo que convierte un ataque de fuerza bruta masivo en algo económicamente inviable.
| Algoritmo | Año | Qué encarece | Nota |
|---|---|---|---|
| PBKDF2 | 2000 | Número de iteraciones | Aceptable; vulnerable a aceleración por GPU |
| bcrypt | 1999 | Factor de coste (iteraciones) | Muy probado; límite de 72 bytes de entrada |
| scrypt | 2009 | Iteraciones + memoria | Resistente a hardware dedicado |
| Argon2id | 2015 | Iteraciones + memoria + paralelismo | Ganador del Password Hashing Competition; opción por defecto hoy |
La razón de que Argon2 y scrypt exijan memoria además de tiempo es frenar a las GPU y los ASIC: esos dispositivos tienen miles de núcleos pero poca memoria rápida por núcleo, así que obligarles a usar mucha RAM por intento elimina su ventaja. Esto conecta directamente con el artículo de Hashcat: un hash Argon2 bien parametrizado reduce la velocidad de cracking de miles de millones por segundo a unos pocos miles.
El caso LastPass 2022, en una línea
Cuando se filtraron las bóvedas cifradas de LastPass, las cuentas antiguas seguían configuradas con 5.000 iteraciones de PBKDF2 en lugar de las 100.100 recomendadas: un factor de trabajo veinte veces menor, y por tanto veinte veces más barato de atacar por fuerza bruta. El número de iteraciones no es un detalle de configuración: es la diferencia entre «irrompible» y «cuestión de presupuesto»
4. Cifrado: reversible, pero solo con la clave
Cifrar es transformar datos de forma que solo quien posee la clave correcta pueda revertir la operación y recuperar el original. A diferencia del hash, el cifrado sí es reversible; a diferencia de la codificación, esa reversión depende de un secreto.
- Cifrado simétrico: la misma clave cifra y descifra (AES-GCM, ChaCha20-Poly1305). Rápido; el reto es repartir la clave de forma segura
- Cifrado asimétrico: una clave pública cifra y una privada descifra (RSA, curva elíptica). Resuelve el reparto de clave a cambio de ser mucho más lento
- En la práctica casi todo usa cifrado híbrido: asimétrico para acordar una clave de sesión, simétrico para los datos. Así funciona TLS, así funciona el cifrado de la mensajería
El cifrado moderno serio es autenticado (AEAD): además de ocultar el contenido, detecta si alguien ha manipulado el mensaje cifrado. Cifrar sin autenticar es un error clásico que abre la puerta a ataques donde el adversario modifica el texto cifrado y observa cómo reacciona el sistema.
Cuándo se cifra y no se hashea: cuando necesitas recuperar el dato. El número de cuenta de un cliente, el cuerpo de un correo, un fichero en un disco perdido, los mensajes de un chat. Cuándo se hashea y no se cifra: cuando solo necesitas comparar, no recuperar. Contraseñas, sobre todo.
5. Los tres errores que se repiten
5.1 «Lo guardo en Base64 para que no se vea»
Base64 no es un mecanismo de seguridad. Un token, una clave de API o una contraseña en Base64 dentro de un fichero de configuración, una cookie o una respuesta de API están, a efectos prácticos, en claro. Si algo debe permanecer secreto, se cifra con una clave gestionada aparte; si además debe ir por un canal de texto, se codifica después de cifrar.
5.2 «Hasheo la contraseña con SHA-256 y listo»
SHA-256 sin sal y sin coste deja las contraseñas comunes al alcance de un diccionario en segundos, y permite usar rainbow tables. La regla es simple: para contraseñas, Argon2id (o bcrypt/scrypt si la plataforma no ofrece Argon2), nunca un hash de propósito general a secas. La mayoría de frameworks web ya traen esto por defecto; el error aparece cuando alguien «se lo monta a mano».
5.3 «Ciframos las contraseñas de los usuarios»
Si una web puede descifrar tu contraseña, es que guarda la clave para hacerlo, y esa clave se filtrará junto con la base de datos el día de la brecha. Las contraseñas de usuario no se cifran: se hashean con un algoritmo de contraseñas. La señal de alarma infalible es un servicio que, al pulsar «he olvidado mi contraseña», te envía la actual por correo en lugar de dejarte crear una nueva.
6. Tabla resumen
| Mecanismo | ¿Tiene clave? | ¿Reversible? | Uso correcto | Uso incorrecto habitual |
|---|---|---|---|---|
| Codificación (Base64, hex) | No | Sí, por cualquiera | Transportar datos por un canal de texto | Ocultar secretos |
| Hash de propósito general (SHA-256, BLAKE2) | No | No | Integridad, firmas, deduplicación | Guardar contraseñas directamente |
| Hash de contraseñas (Argon2, bcrypt, scrypt) | No (usa sal) | No | Almacenar credenciales de login | Datos que luego hay que recuperar |
| Cifrado simétrico (AES-GCM) | Sí (una) | Sí, con la clave | Datos en reposo y en tránsito | Contraseñas de usuario |
| Cifrado asimétrico (RSA, ECC) | Sí (par pública/privada) | Sí, con la privada | Acordar claves, firmar, cifrar mensajes cortos | Cifrar grandes volúmenes directamente |
Referencias
OWASP Password Storage Cheat Sheet — parámetros concretos y actualizados para Argon2, bcrypt y scrypt · NIST SP 800-63B — guía de gestión de credenciales y verificadores · RFC 9106 (Argon2) y la Password Hashing Competition (password-hashing.net) · CyberChef (gchq.github.io/CyberChef) — para ver en vivo cómo se deshace una codificación · Nuestros artículos sobre Hashcat, gestores de contraseñas y JWT, que se apoyan en estos conceptos
Conclusión
Codificar cambia el formato y lo deshace cualquiera. Hashear produce una huella de un solo sentido que sirve para verificar, no para recuperar. Cifrar oculta el contenido de forma reversible, pero solo para quien tiene la clave. Son tres herramientas para tres trabajos y no son intercambiables.
La prueba de fuego para elegir: ¿necesito recuperar el dato original más adelante? Si sí, es cifrado, y la pregunta siguiente es dónde vive la clave. Si solo necesito comprobar que alguien conoce un secreto sin guardarlo, es un hash de contraseñas con sal y coste. Y si lo único que quiero es que un dato viaje intacto por un canal de texto, es codificación, que no protege nada y no pretende hacerlo.
unfantasmaenelsistema.com | Seguridad, sistemas y todo lo que no debería funcionar (pero funciona)

