Encriptación AES en MySQL (y MaríaDB)

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.

Anuncios

21 comentarios en “Encriptación AES en MySQL (y MaríaDB)

  1. Pingback: Encriptación AES en MySQL (y MaríaDB) « DbRunas – Noticias y Recursos sobre Bases de Datos

  2. Luis

    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 😉

  3. Luis

    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?

  4. 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!

  5. Julio

    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

    1. 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′”);

  6. Luis

    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…

  7. Luis

    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!!!

      1. Luisinho

        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)

        😥

  8. Helmer Mendoza

    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

  9. Pingback: Tabla Usuario | luisenriquemedinatorres

  10. oriol

    Hola necesito saber como cifrar con AES una columna especifica en MysQL, teniendo en cuenta que yatengo datos almacenados en la base de datos

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s