La seguridad de los datos es una preocupación fundamental en cualquier aplicación que gestione información sensible, y las contraseñas de usuario son, sin duda, uno de los elementos más críticos a proteger. Almacenar contraseñas en texto plano es una práctica extremadamente peligrosa que expone a los usuarios a graves riesgos en caso de una brecha de seguridad. Afortunadamente, los sistemas de gestión de bases de datos como MySQL ofrecen funciones integradas que permiten "cifrar" (o, más precisamente, hashear) estas contraseñas antes de almacenarlas, añadiendo una capa esencial de defensa.

Este artículo explora las diversas funciones que MySQL pone a nuestra disposición para este fin, analizando su propósito, uso y, crucialmente, su idoneidad en el contexto de la seguridad moderna. Entender cómo y cuándo usar cada una es vital para implementar una estrategia de protección robusta.

- ¿Por Qué Nunca Debes Almacenar Contraseñas en Texto Plano?
- Hashing vs. Cifrado: Una Distinción Crucial
- Funciones Hash de Contraseñas en MySQL
- Comparativa de Funciones Hash en MySQL para Contraseñas
- La Mejor Práctica: Hashing Adaptable a Nivel de Aplicación
- Implementando el Hashing en MySQL (Usando SHA2 como Ejemplo)
- Preguntas Frecuentes (FAQ)
- Conclusión
¿Por Qué Nunca Debes Almacenar Contraseñas en Texto Plano?
La respuesta es simple y contundente: una base de datos comprometida con contraseñas en texto plano significa que los atacantes obtienen acceso inmediato y utilizable a las credenciales de todos tus usuarios. Esto no solo afecta a tu aplicación, sino que, dado que muchos usuarios reutilizan contraseñas, puede comprometer sus cuentas en otros servicios (correo electrónico, banca online, redes sociales, etc.). Las consecuencias pueden ser devastadoras, incluyendo pérdida de confianza, daños a la reputación, responsabilidades legales y pérdidas económicas.
El objetivo es que, incluso si un atacante accede a la tabla de usuarios, no pueda obtener las contraseñas originales. Aquí es donde entran en juego las técnicas de hashing.
Hashing vs. Cifrado: Una Distinción Crucial
Aunque comúnmente se habla de "cifrar" contraseñas, la técnica más adecuada para almacenar contraseñas es el hashing, no el cifrado tradicional. Es fundamental comprender la diferencia:
- Cifrado (Encryption): Es un proceso bidireccional. Transforma datos legibles (texto plano) en un formato ilegible (texto cifrado) utilizando una clave, de tal manera que pueden ser revertidos a su estado original (descifrados) si se posee la clave correcta. Es útil para proteger datos en tránsito o en reposo que necesitan ser recuperados en su forma original (por ejemplo, información de tarjetas de crédito, correos electrónicos confidenciales).
- Hashing: Es un proceso unidireccional. Transforma datos (la contraseña) en una cadena de longitud fija (el hash o resumen) utilizando una función matemática. Este proceso es diseñado para ser irreversible; es computacionalmente inviable obtener la contraseña original a partir de su hash. Cuando un usuario intenta iniciar sesión, la contraseña que ingresa se hashea con la misma función y el resultado se compara con el hash almacenado en la base de datos. Si los hashes coinciden, la contraseña es correcta.
Para contraseñas, queremos que sean imposibles de recuperar si la base de datos se ve comprometida, por lo tanto, utilizamos funciones hash.
Funciones Hash de Contraseñas en MySQL
MySQL proporciona varias funciones que pueden ser utilizadas para generar hashes de contraseñas. Es importante conocerlas y entender sus fortalezas y debilidades.
PASSWORD(cadena)
Esta función es la que MySQL utiliza internamente para cifrar las contraseñas de los usuarios del propio servidor MySQL (las que se almacenan en la tabla mysql.user). Genera un hash basado en un algoritmo propietario de MySQL. Históricamente, ha tenido diferentes versiones (protocolo de autenticación antiguo y nuevo).
Uso:
SELECT PASSWORD('mi_contraseña_secreta');Consideraciones:
- Genera un hash específico de MySQL.
- No es recomendable para almacenar contraseñas de usuarios de tu aplicación, ya que está diseñada para el sistema de autenticación interno de MySQL y su algoritmo ha evolucionado y no siempre es el más robusto para aplicaciones generales.
- En versiones recientes de MySQL (8.0+), el método de autenticación por defecto ha cambiado, haciendo que
PASSWORD()sea menos relevante para nuevas instalaciones. - No utiliza salting explícito por parte del usuario.
No se recomienda usar PASSWORD() para las contraseñas de tus usuarios de aplicación.
ENCRYPT(cadena, salt)
Esta función implementa un algoritmo de hashing (basado en la función crypt() de Unix) que permite especificar un "salt". El salt es una cadena aleatoria que se añade a la contraseña antes de hashearla. Esto hace que dos usuarios con la misma contraseña tengan hashes diferentes, protegiendo contra ataques de tablas arcoíris (rainbow tables).
Uso:
SELECT ENCRYPT('mi_contraseña', 'mi_salt'); -- El salt suele ser generado aleatoriamenteConsideraciones:
- Requiere un salt.
- El algoritmo subyacente (basado en
crypt()) puede ser antiguo y limitado (por ejemplo, solo usa los primeros 8 caracteres de la contraseña en algunas implementaciones). - Su disponibilidad depende del sistema operativo subyacente y de la configuración de MySQL; a menudo está deshabilitada o no disponible.
- No es adaptable (el tiempo de procesamiento es fijo, lo que facilita ataques de fuerza bruta con hardware potente).
Debido a sus limitaciones y dependencia del sistema, no se recomienda para nuevas aplicaciones.
MD5(cadena)
MD5 (Message-Digest Algorithm 5) es una función hash criptográfica que produce un hash de 128 bits (32 caracteres hexadecimales). Fue muy popular en el pasado.
Uso:
SELECT MD5('mi_contraseña');Consideraciones:
- Es rápido de calcular.
- Es vulnerable a colisiones: Es posible encontrar dos entradas diferentes que produzcan el mismo hash MD5.
- Es susceptible a ataques de fuerza bruta y ataques de diccionario/tablas arcoíris debido a su velocidad y a la falta de salting inherente (aunque se puede añadir un salt manualmente concatenándolo a la cadena antes de hashear).
MD5 está completamente obsoleto y es inseguro para el almacenamiento de contraseñas debido a su debilidad.
SHA1(cadena)
SHA1 (Secure Hash Algorithm 1) es otra función hash criptográfica, considerada más robusta que MD5 en su momento. Produce un hash de 160 bits (40 caracteres hexadecimales).
Uso:
SELECT SHA1('mi_contraseña');Consideraciones:
- Más lento que MD5, lo que lo hace ligeramente más resistente a la fuerza bruta (pero aún así es rápido para los estándares modernos).
- Aunque las colisiones son más difíciles de encontrar que en MD5, SHA1 también se considera criptográficamente débil y ha sido demostrado que es susceptible a ataques de colisión prácticos.
- No incluye salting por defecto.
SHA1 también se considera inseguro y obsoleto para el almacenamiento de contraseñas.
SHA2(cadena, longitud)
SHA2 es una familia de funciones hash criptográficas (SHA-224, SHA-256, SHA-384, SHA-512) consideradas mucho más seguras que MD5 y SHA1. MySQL implementa SHA-256 y SHA-512 a través de la función SHA2(), donde el segundo argumento especifica la longitud del hash deseada (256 o 512 bits). Si se omite la longitud, por defecto es 256 bits.
Uso:
SELECT SHA2('mi_contraseña', 256); -- Genera un hash SHA-256 (64 caracteres) SELECT SHA2('mi_contraseña', 512); -- Genera un hash SHA-512 (128 caracteres) SELECT SHA2('mi_contraseña', 0); -- Es equivalente a SHA2(cadena, 256)Consideraciones:
- Son algoritmos mucho más robustos y resistentes a colisiones que MD5 y SHA1.
- Son más lentos que MD5 y SHA1, lo que incrementa el costo computacional para un atacante que intente fuerza bruta.
- Aunque
SHA2()en MySQL no implementa un salting automático y robusto como las funciones modernas (bcrypt, scrypt, Argon2), son la opción más segura entre las funciones hash nativas de MySQL si debes usarlas.
SHA2() es la función hash más segura disponible nativamente en MySQL para propósitos generales, aunque las funciones hash adaptables a nivel de aplicación son preferibles.
Comparativa de Funciones Hash en MySQL para Contraseñas
| Función | Algoritmo | Longitud Hash | Salt Incluido | Recomendación para Contraseñas de Aplicación |
|---|---|---|---|---|
PASSWORD() | Propietario MySQL | Variable | No (interno) | No (específico de MySQL, obsoleto) |
ENCRYPT() | Unix crypt() (variante) | Fija (variable según SO) | Sí (explícito) | No (obsoleto, dependiente del SO, lento) |
MD5() | MD5 | 128 bits (32 chars) | No | Nunca (inseguro, colisiones) |
SHA1() | SHA1 | 160 bits (40 chars) | No | Nunca (inseguro, colisiones) |
SHA2(cadena, 256) | SHA-256 | 256 bits (64 chars) | No (se puede añadir salt manual) | Aceptable (si no hay otra opción), pero mejor funciones adaptables |
SHA2(cadena, 512) | SHA-512 | 512 bits (128 chars) | No (se puede añadir salt manual) | Aceptable (si no hay otra opción), pero mejor funciones adaptables |
La Mejor Práctica: Hashing Adaptable a Nivel de Aplicación
Aunque SHA2() es la opción más segura entre las funciones nativas de MySQL, la recomendación de seguridad moderna es realizar el hashing de contraseñas a nivel de la aplicación (en PHP, Python, Java, Node.js, etc.) utilizando funciones hash *adaptables* y *resistentes a la fuerza bruta*.
Funciones como bcrypt, scrypt y Argon2 están diseñadas específicamente para el hashing de contraseñas. Tienen varias ventajas clave:
- Son lentas (deliberadamente): Requieren más tiempo y recursos computacionales para calcular un hash, lo que ralentiza enormemente los ataques de fuerza bruta.
- Son adaptables: Permiten ajustar un "factor de trabajo" (work factor) que aumenta la lentitud. A medida que el hardware se vuelve más rápido, puedes aumentar el factor de trabajo para mantener el mismo nivel de seguridad.
- Incluyen salting de forma nativa: Generan y gestionan un salt único para cada contraseña de forma automática.
- Son resistentes a hardware especializado (ASICs/GPUs): Algunas están diseñadas para ser más difíciles de acelerar con hardware específico.
Cuando utilizas estas funciones, almacenas en la base de datos el hash resultante *junto con el salt utilizado* (a menudo el salt está incrustado en el propio hash). Al verificar una contraseña, recuperas el hash almacenado y el salt, y hasheas la contraseña ingresada por el usuario usando la misma función y salt, comparando luego los resultados.
Implementar el hashing a nivel de aplicación libera a la base de datos de esta tarea y te permite usar algoritmos más modernos y seguros que no están limitados por las funciones integradas de MySQL.
Implementando el Hashing en MySQL (Usando SHA2 como Ejemplo)
Si por alguna razón debes usar funciones de MySQL (aunque no sea lo ideal), aquí tienes un ejemplo básico de cómo almacenar y verificar contraseñas usando SHA2().
Estructura de la Tabla
Necesitas un campo para el hash de la contraseña. Dado que SHA-256 produce 64 caracteres hexadecimales y SHA-512 produce 128, un campo VARCHAR o CHAR con la longitud adecuada es necesario.
CREATE TABLE usuarios ( id INT AUTO_INCREMENT PRIMARY KEY, nombre_usuario VARCHAR(50) UNIQUE NOT NULL, contraseña_hash CHAR(128) NOT NULL COMMENT 'Usamos SHA-512, que produce 128 caracteres' );Nota: Usar CHAR(128) es eficiente porque SHA-512 siempre produce exactamente 128 caracteres. Si usaras SHA-256, sería CHAR(64).
Almacenar una Contraseña
Cuando un usuario se registra o cambia su contraseña, calculas el hash y lo insertas:
INSERT INTO usuarios (nombre_usuario, contraseña_hash) VALUES ('nuevo_usuario', SHA2('mi_contraseña_secreta123', 512));Verificar una Contraseña
Cuando un usuario intenta iniciar sesión, calculas el hash de la contraseña que ingresa y lo comparas con el hash almacenado en la base de datos:
SELECT id FROM usuarios WHERE nombre_usuario = 'nuevo_usuario' AND contraseña_hash = SHA2('contraseña_ingresada_por_usuario', 512);Si la consulta devuelve una fila, la contraseña es correcta. Si no devuelve nada, la contraseña es incorrecta.
Este ejemplo es básico y no incluye salting, que es crucial. Para añadir salting con SHA2() en MySQL, tendrías que generar un salt aleatorio en tu aplicación, concatenarlo a la contraseña antes de hashearla, y almacenar tanto el hash resultante como el salt utilizado en la base de datos. Al verificar, recuperarías el salt almacenado, lo concatenarías a la contraseña ingresada y hashearías para comparar.
Preguntas Frecuentes (FAQ)
P: ¿Cuál es la función más segura para cifrar contraseñas en MySQL?
R: Entre las funciones nativas de MySQL, SHA2(cadena, 512) o SHA2(cadena, 256) son las más seguras. Sin embargo, las funciones hash adaptables a nivel de aplicación (bcrypt, scrypt, Argon2) son la recomendación estándar de la industria hoy en día.
P: ¿Puedo descifrar un hash MD5 o SHA1 para obtener la contraseña original?
R: No, por definición, las funciones hash son unidireccionales e irreversibles. No puedes obtener la contraseña original a partir de su hash. Los atacantes utilizan otros métodos como tablas arcoíris o ataques de fuerza bruta para intentar adivinar la contraseña que produjo un hash determinado.
P: ¿Por qué MD5 y SHA1 ya no son seguros para contraseñas?
R: Son demasiado rápidos de calcular, lo que facilita los ataques de fuerza bruta. Además, son vulnerables a ataques de colisión y no ofrecen protección inherente contra tablas arcoíris sin salting manual.
P: ¿Qué es el "salt" y por qué es importante?
R: Un salt es una cadena aleatoria única que se añade a la contraseña antes de hashearla. Su importancia radica en que garantiza que dos contraseñas idénticas produzcan hashes diferentes, defendiendo así contra ataques de tablas arcoíris y haciendo que cada contraseña requiera un esfuerzo de fuerza bruta individual para ser descifrada.
P: ¿Debería usar PASSWORD() para las contraseñas de mis usuarios?
R: No. PASSWORD() está diseñado para el sistema de autenticación interno de MySQL y no es adecuado ni recomendado para las contraseñas de los usuarios de tu aplicación.
P: Si uso SHA2 en MySQL, ¿necesito salting?
R: Sí, absolutamente. Aunque SHA2 es un algoritmo fuerte, sin un salt único para cada contraseña (gestionado manualmente al usar SHA2()), sigues siendo vulnerable a ataques de tablas arcoíris si los atacantes precalculan hashes para contraseñas comunes. Es mejor usar SHA2 con salting (concatenando un salt único a la cadena antes de hashear y almacenando el salt) o, idealmente, usar funciones adaptables a nivel de aplicación que manejan el salting automáticamente.
Conclusión
Proteger las contraseñas de tus usuarios es una de las responsabilidades más importantes en el desarrollo de aplicaciones. Nunca almacenes contraseñas en texto plano. Si bien MySQL ofrece funciones como MD5(), SHA1() y SHA2(), las dos primeras son inseguras y la última, aunque más robusta, carece de las características de seguridad (como el salting automático y la adaptabilidad) que ofrecen las funciones hash modernas. La mejor práctica actual es utilizar algoritmos hash adaptables como bcrypt, scrypt o Argon2 a nivel de la aplicación. Sin embargo, si te ves limitado a usar funciones de MySQL, SHA2() (con salting manual si es posible) es la opción menos mala. Prioriza siempre la seguridad y mantente actualizado sobre las recomendaciones de hashing de contraseñas.
Si quieres conocer otros artículos parecidos a Cifrado de Contraseñas en MySQL: Guía Completa puedes visitar la categoría Seguridad.

Aprende mas sobre MySQL