El uso de la encriptación AES en MySQL (la más segura de la que dispone el famoso SGBD) es sencillo, y se realiza mediante dos funciones: AES_ENCRYPT y AES_DECRYPT. Permite usar AES_128 o AES_256 dependiendo de la fuente que usemos.
Para insertar o modificar los datos de una columna basta con hacer uso de AES_ENCRYPT, que recibe dos parámetros: el dato a insertar (string) y la clave (string también). A diferencia de SQL-Server, en este caso el dato a encriptar siempre es una cadena. Si quieres conocer de antemano la longitud de la cadena resultado (para ajustar el tamaño del campo en la tabla) lo puedes hacer recurriendo a la fórmula 16 * (trunc(logintud_de_la_cadena / 16) + 1). Si recibe un argumento null el resultado será null también.
Para el caso de AES_DECRYPT los parámetros serán la cadena encriptada a descifrar y la contraseña. Si hay algún error en la encriptación (sea por una modificación maliciosa o por datos de entrada incorrectos) esta función devolverá NULL, aunque es posible que en algún caso pueda dar un valor no nulo erróneo si la cadena encriptada o la contraseña son erróneas.
Una inserción de un registro encriptado se ralizaría de la siguiente forma:
INSERT INTO tb_Ejemplo VALUES(AES_ENCRYPT('valor a encriptar como cadena', 'contraseña'));
En este caso si realizamos una select normal nos devolvería los datos encriptados, para poder verlos tendríamos que hacer
SELECT AES_DECRYPT(COLUMNA_ENCRIPTADA, 'contraseña') FROM tb_Ejemplo;
Finalmente, por seguridad podemos guardar la contraseña en una variable del servidor para no enviarla en cada comunicación con la base de datos, tal que así:
SELECT @pss:='password'; INSERT INTO tb_Ejemplo VALUES (AES_ENCRYPT('texto',@pss));
Sobre cifrado tanto MySQL como MariaDB ofrecen varias opciones aparte de AES, que en este caso es la comentada por ser la más segura y robusta. Pero también existe la posibilidad de usar DES (DES_ENCRYPT y DES_DECRYPT), las funciones DECODE y ENCODE (que no se qué algoritmo usan, la verdad, pero que nos obligan a almacenar los datos en una columna tipo BLOB) y para hashes las funciones MD5, SHA1 y ENCRYPT (que llama a la función crypt() de UNIX, por lo que no puede usarse en Windows). También existe la función PASSWORD, pero es la que usa el sistema de autenticación de MySQL, por lo que se recomienda no usarla en aplicaciones propias.
Pingback: Encriptación AES en MySQL (y MaríaDB) « DbRunas – Noticias y Recursos sobre Bases de Datos
Gracias por el artículo, pero una cosa que no me ha quedado muy clara es cómo guardar la contraseña en el servidor, ¿hay que hacerlo en consola de mySQL? O cada vez que se establece la conexión…
Gracias 😉
Tienes diversas opciones para ello: usarla en cada consulta, gurdarla en un archivo externo, en un procedimiento almacenado… depende de las necesidade y de la seguridad.
Genial Donnie, he estado buscando el tema de los procedimientos, parece que es lo más liviano para el servidor… ¿se podría hacer un procedimiento para que siempre encripte unos campos de una tabla al grabarlos y los devuelva desencriptados al leerlos?
Sí, y es más, es un artículo que lleva tiempo en mi TODO list, pero estos meses estoy liado de chollo. Esta semana lo escribo… jejeje
esperaré como agua de mayo 😉
https://donnierock.com/2014/03/29/stored-procedure-para-guardar-y-devolver-datos-encriptados-con-aes-mysql/ Aquí lo tienes, Luis
Hola Donnie, Recien encuentro tu blog y ya llevo medio dia dando scroll y leyendo artículos… muy bueno… tengo una pregunta sobre este tema. si yo encripto, por ejemplo el numero de identificacion de mis clientes. y requiero hacer una búsqueda de un número específico lo ideal sería buscar la encripcion de dicho número cierto?, algo así:
s e l e c t AES_DECRYPT(documento, ‘contraseña’) as d, AES_DECRYPT(NOMBRE, ‘contraseña’) as n FROM tb_Ejemplo where AES_ENCRYPT(‘numerodocumento’, ‘contraseña’)
aunque no he probado, asumo que funciona, lo que no se es si es la manera correcta, espero comentarios. Gracias!
Nota el s e l e c t lo puse separado porque inicialmente me dijo que no podia guardar el comentario… asumí que fuera por eso…
Donnie, gracias por el tema, sin embargo al realizar una consulta no me está arrojado datos, mi
consulta es:
$sqla = mysql_query(“SELECT AES_DECRYPT(nombre, ‘password’) FROM test_depa where dep_id =’07′”);
if($fa= mysql_fetch_array($sqla)){
echo $fa[‘nombre’];}
Si quito AES_DECRY.PT me imprime el registro encriptado
Muchas gracias
Al usar una función en un select se pierde el nombre de columna, creo que ahí está lo que te está machacando, prueba con
$sqla = mysql_query(“SELECT AES_DECRYPT(nombre, ‘password’) as ‘nombre’ FROM test_depa where dep_id =’07′”);
Hola Julio, le tienes que asigna el alias “nombre” al campo recogido, a mí también me pasó…
… SELECT AES_DECRYPT(nombre, ‘password’) as nombre FROM…
jeje, perdona, vi el coment y respondí… se cruzaron las respuestas…
Donniel, lo que me he dado cuenta es que ahora las búsquedas que se hacen en mySQL son sensibles a mayúsculas y minúsculas… ¿cómo evitarlo?
SELECT AES_DECRYPT(nombre,”mipass”) as nombre, AES_DECRYPT(apellidos,”mipass”) as apellidos
FROM usuarios
WHERE 1
AND (AES_DECRYPT(nombre,”mipass”) LIKE “%luis%” OR AES_DECRYPT(apellidos,”mipass”) LIKE “%luis%” OR CONCAT(AES_DECRYPT(nombre,”mipass”), ” “,AES_DECRYPT(apellidos,”mipass”)) LIKE “%luis%”)
He probado esto, pero no me funciona, pero si lo escribo en mayúculas sí que lo encuentra:
SELECT AES_DECRYPT(nombre,”mipass”) as nombre, AES_DECRYPT(apellidos,”mipass”) as apellidos
FROM usuarios
WHERE 1
AND LOWER((AES_DECRYPT(nombre,”mipass”)) LIKE “%’.strtolower($buscar).’%” OR AND LOWER(AES_DECRYPT(apellidos,”mipass”)) LIKE “%’.strtolower($buscar).’%” OR AND LOWER(CONCAT(AES_DECRYPT(nombre,”mipass”), ” “,AES_DECRYPT(apellidos,”mipass”))) LIKE “%’.strtolower($buscar).’%”)
Gracias por la ayuda!!!
No sé si esta entrada del manual podrá ayudarte: http://dev.mysql.com/doc/refman/5.0/es/case-sensitivity.html
Hola Donnie, vuelvo a la carga… por lo visto los campos BLOB guardan la información de forma binaria, con lo que no encuentra coincidencias entre “a” y”A”… ya que la comparación la hace bit a bit, la “A” es el binario 65 (1000001) y “a” el 97 (1100001)
😥
Buenas una consulta la columna de mi tabla donde pondre el valor encriptado que tipo debe ser porque uso char y varchar pero no lo guarda bien ni lo despliega bien, muchas gracias por tu respuesta y un saludo desde Bolivia
Prueba con una columna tipo BLOB
ok asi logre guardar la información, pero el problema esta en el despliegue, me pudieras dar un ejemplo
Tienes un ejemplo en esta otra entrada sobre el tema, donde vemos cómo hacerlo con un procedimiento almacenado:
https://donnierock.com/2014/03/29/stored-procedure-para-guardar-y-devolver-datos-encriptados-con-aes-mysql/
Pingback: Tabla Usuario | luisenriquemedinatorres
Hola necesito saber como cifrar con AES una columna especifica en MysQL, teniendo en cuenta que yatengo datos almacenados en la base de datos
Que hago si quiero averiguar la contraseña de root directamente desde un gestor de base de datos? como query browser de mysql
Hola, muy bueno el articulo, gracias por la información, que recomendarías para almacenar una típica contraseña que va con valores de mínimo 8 máximo 15 caracteres. CHAR o VARCHAR? cual de los 2 es mas eficiente?