MD5 en MySQL
La función MD5() en MySQL calcula un hash de 128 bits a partir de cualquier cadena de texto y devuelve su representación hexadecimal de 32 caracteres. Este algoritmo de resumen, diseñado originalmente por Ronald Rivest en 1991, transforma una entrada de longitud arbitraria en una huella digital de tamaño fijo. En el contexto de bases de datos, MD5 resulta especialmente útil para verificar la integridad de datos, generar identificadores únicos para deduplicación y crear claves de caché eficientes. Aunque MD5 ya no se considera seguro para fines criptográficos, sigue siendo una herramienta práctica y rápida para tareas que no requieren resistencia ante ataques.
Sintaxis de MD5
La sintaxis de la función MD5 es directa y acepta un único argumento de tipo cadena. MySQL convierte automáticamente valores numéricos u otros tipos a su representación en texto antes de calcular el hash.
MD5(cadena)El valor devuelto es siempre una cadena hexadecimal en minúsculas de exactamente 32 caracteres. Si el argumento es NULL, la función devuelve NULL. Internamente, MySQL procesa la cadena byte a byte, lo que significa que el resultado depende del juego de caracteres de la conexión. Dos cadenas que se muestran igual pero están codificadas de forma distinta pueden producir hashes diferentes, así que conviene asegurarse de que la codificación sea consistente.
SELECT MD5('Tutorial MySQL');
-- Resultado: un hash de 32 caracteres hexadecimales
SELECT MD5('tutorial mysql');
-- Resultado diferente: MD5 distingue mayúsculas y minúsculas
SELECT MD5(NULL);
-- Resultado: NULLEs importante comprender que MD5 es una función determinista: la misma entrada siempre produce la misma salida. Esta propiedad es fundamental para todas las aplicaciones que veremos a continuación, ya que permite comparar hashes de forma fiable.
Verificación de integridad de datos
Uno de los usos más naturales de MD5 es comprobar si los datos han cambiado o se han corrompido. Cuando almacenas el hash de un valor en el momento de su inserción, puedes recalcularlo después y comparar ambos hashes para detectar cualquier alteración.
Imagina una tabla que almacena documentos junto con un hash de verificación. Cada vez que se inserta un documento, se calcula su MD5 y se guarda en una columna dedicada.
CREATE TABLE documentos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(255) NOT NULL,
contenido LONGTEXT NOT NULL,
hash_md5 CHAR(32) NOT NULL,
fecha_creacion DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO documentos (nombre, contenido, hash_md5)
VALUES (
'contrato-2026.pdf',
'Contenido completo del contrato de servicios profesionales...',
MD5('Contenido completo del contrato de servicios profesionales...')
);Para verificar la integridad más adelante, basta con recalcular el hash del contenido actual y compararlo con el almacenado.
SELECT
nombre,
CASE
WHEN hash_md5 = MD5(contenido) THEN 'Íntegro'
ELSE 'Modificado'
END AS estado_integridad
FROM documentos;Esta técnica es especialmente valiosa en sistemas donde los datos pasan por múltiples procesos de transformación o migración. Si el hash recalculado no coincide con el original, sabes con certeza que algo cambió en el camino.
Identificadores únicos para deduplicación
MD5 permite generar identificadores compactos a partir de combinaciones de campos, lo que resulta muy útil para detectar registros duplicados. En lugar de comparar múltiples columnas una por una, puedes comparar un único hash que representa la combinación de todas ellas.
Considera un sistema de importación de productos donde necesitas evitar duplicados basándote en nombre, categoría y proveedor.
CREATE TABLE productos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(200) NOT NULL,
categoria VARCHAR(100) NOT NULL,
proveedor VARCHAR(150) NOT NULL,
precio DECIMAL(10,2) NOT NULL,
hash_dedup CHAR(32) NOT NULL,
INDEX idx_dedup (hash_dedup)
);
-- Al insertar, generar el hash de deduplicación
INSERT INTO productos (nombre, categoria, proveedor, precio, hash_dedup)
VALUES (
'Monitor UltraWide 34"',
'Periféricos',
'Samsung Electronics',
549.99,
MD5(CONCAT('Monitor UltraWide 34"', '|', 'Periféricos', '|', 'Samsung Electronics'))
);Antes de cada importación masiva, puedes comprobar si ya existe un producto con el mismo hash. La comparación de una sola columna indexada de 32 caracteres es mucho más rápida que comparar tres columnas de texto de longitud variable.
-- Verificar si un producto ya existe antes de insertar
SELECT id, nombre
FROM productos
WHERE hash_dedup = MD5(CONCAT('Monitor UltraWide 34"', '|', 'Periféricos', '|', 'Samsung Electronics'));El separador | entre los campos evita colisiones accidentales. Sin separador, la combinación 'AB' + 'CD' produciría el mismo hash que 'A' + 'BCD', lo que generaría falsos positivos de duplicación.
Claves de caché
Otro uso frecuente de MD5 es la generación de claves de caché. Cuando tu aplicación ejecuta consultas costosas cuyo resultado se almacena temporalmente, necesitas una clave única que identifique cada consulta y sus parámetros. MD5 transforma cualquier combinación de parámetros en una clave compacta y uniforme.
CREATE TABLE cache_consultas (
cache_key CHAR(32) PRIMARY KEY,
resultado JSON NOT NULL,
creado_en DATETIME DEFAULT CURRENT_TIMESTAMP,
expira_en DATETIME NOT NULL
);
-- Generar clave de caché a partir de los parámetros de una consulta
SET @parametros = CONCAT('informe_ventas', '|', '2026-01', '|', 'region_norte');
-- Buscar en caché
SELECT resultado
FROM cache_consultas
WHERE cache_key = MD5(@parametros)
AND expira_en > NOW();
-- Si no existe en caché, almacenar el resultado
INSERT INTO cache_consultas (cache_key, resultado, expira_en)
VALUES (
MD5(@parametros),
'{"total": 158430.50, "transacciones": 2847}',
DATE_ADD(NOW(), INTERVAL 1 HOUR)
)
ON DUPLICATE KEY UPDATE
resultado = VALUES(resultado),
creado_en = NOW(),
expira_en = DATE_ADD(NOW(), INTERVAL 1 HOUR);Al usar MD5 como clave primaria del caché, aprovechas que el hash tiene longitud fija y distribuye los valores uniformemente, lo que mejora el rendimiento de las búsquedas por índice.
Comparar contenido de registros entre tablas
MD5 es una herramienta excelente para comparar grandes volúmenes de datos entre dos tablas, por ejemplo durante una migración o sincronización. En lugar de comparar cada columna individualmente, puedes calcular el hash de toda la fila y comparar únicamente ese valor.
-- Comparar datos entre tabla de producción y réplica
SELECT p.id, 'Datos divergentes' AS estado
FROM produccion.clientes p
JOIN replica.clientes r ON p.id = r.id
WHERE MD5(CONCAT_WS('|', p.nombre, p.email, p.telefono, p.direccion))
!= MD5(CONCAT_WS('|', r.nombre, r.email, r.telefono, r.direccion));La función CONCAT_WS es preferible a CONCAT en este contexto porque maneja los valores NULL de forma más predecible, insertando el separador solo entre valores no nulos. Si necesitas profundizar en funciones de cadena relacionadas, consulta la documentación sobre LENGTH para entender cómo MySQL mide las cadenas que alimentan a MD5.
Advertencia de seguridad: MD5 no es apto para contraseñas
Es fundamental entender que MD5 no debe usarse para almacenar contraseñas ni para ningún propósito donde la seguridad criptográfica sea importante. Desde 2004, se han demostrado colisiones prácticas en MD5, lo que significa que es posible encontrar dos entradas diferentes que producen el mismo hash. Además, existen tablas rainbow y bases de datos precalculadas que permiten revertir millones de hashes MD5 comunes en segundos.
-- NUNCA hagas esto para contraseñas
-- ❌ Incorrecto e inseguro
INSERT INTO usuarios (email, password_hash)
VALUES ('ana@ejemplo.com', MD5('mi_contraseña_123'));Para almacenar contraseñas de forma segura, la mejor práctica es usar funciones de hashing diseñadas específicamente para ese propósito, como bcrypt o Argon2, desde la capa de aplicación. Si necesitas hashes más robustos dentro de MySQL, las funciones SHA1 y SHA2 ofrecen mayor resistencia, aunque tampoco son la solución ideal para contraseñas por sí solas.
La velocidad de MD5, que es una ventaja para tareas de integridad y deduplicación, se convierte en una debilidad para contraseñas: un atacante puede probar miles de millones de combinaciones por segundo con hardware moderno.
Errores comunes al usar MD5
Existen varios errores frecuentes que conviene evitar al trabajar con MD5 en MySQL. El primero es olvidar que MD5 distingue entre mayúsculas y minúsculas en la entrada. Si normalizas los datos de forma inconsistente, obtendrás hashes diferentes para valores que consideras equivalentes.
-- Estos producen hashes distintos
SELECT MD5('García'); -- un hash
SELECT MD5('garcía'); -- otro hash diferente
-- Normalizar antes de calcular el hash
SELECT MD5(LOWER('García'));
SELECT MD5(LOWER('garcía'));
-- Ahora ambos producen el mismo hashEl segundo error común es no considerar los espacios en blanco. Un espacio al final de una cadena cambia completamente el hash resultante, y esto puede pasar inadvertido durante la importación de datos desde archivos CSV o fuentes externas.
-- Cuidado con espacios invisibles
SELECT MD5('producto'); -- hash A
SELECT MD5('producto '); -- hash B (diferente)
-- Siempre limpiar los datos
SELECT MD5(TRIM('producto ')); -- hash A (correcto)El tercer error es almacenar el hash en una columna VARCHAR en lugar de CHAR(32). Dado que MD5 siempre devuelve exactamente 32 caracteres, usar CHAR(32) es más eficiente en almacenamiento y comparación porque MySQL no necesita manejar longitudes variables.
Cuándo usar MD5
MD5 sigue siendo una opción perfectamente válida cuando la seguridad criptográfica no es un requisito. Úsalo para generar identificadores de deduplicación, crear claves de caché, verificar la integridad de datos en procesos internos y comparar contenido entre tablas durante migraciones. Su principal ventaja frente a alternativas como SHA2 es la velocidad: MD5 es considerablemente más rápido de calcular, lo que marca la diferencia en operaciones masivas sobre millones de registros.
Evita MD5 en cualquier escenario donde un atacante pueda beneficiarse de encontrar colisiones o revertir el hash. Para esos casos, las funciones de la familia SHA2, especialmente SHA2(valor, 256), son la alternativa recomendada dentro de MySQL. Puedes consultar todos los detalles en la guía sobre SHA1 y SHA2.
Escrito por Eduardo Lázaro
