mysql

Cifrado de datos en MySQL con AES

AES (Advanced encryption standard) es un algoritmo bastante fuerte y seguro, utilizado ampliamente en el mundo de la seguridad informática.

MySQL permite cifrar y descifrar datos utilizando el algoritmo AES a través de las funciones aes_encrypt y aes_decrypt.

Cifrar y descifrar con AES en MySQL

De esta manera podemos proteger y asegurar datos utilizando AES.

En este post vamos a ver cómo cifrar y descifrar datos con AES en MySQL.

Sintaxis de aes_encrypt y aes_decrypt

Ambas funciones trabajan de una manera similar. Reciben como primer argumento el texto a cifrar o descifrar, y como segundo argumento la clave.

Es decir:

aes_encrypt("texto_plano", "clave")

Y:

aes_decrypt("texto_cifrado", "clave")

Es importante mencionar que al encriptar se devuelven datos binarios, así que hay que definir (dentro de la tabla) el tipo de dato como BLOB, o utilizar una alternativa que veremos más abajo.

Ejemplo de cifrado y descifrado AES con MySQL

Primero, una consideración sobre la contraseña: nunca guardes la contraseña o clave de cifrado en la base de datos, guárdala en un lugar separado o ni siquiera la guardes.

Es decir, si la encriptación de datos es distinta por usuario haz que la clave sea algo como un hash con su contraseña, o cosas de esas. Si la encriptación es general, usa la misma clave para todos, pero mantenla en un lugar seguro.

Voy a crear esta tabla sin fijarme en relaciones, buenas prácticas ni normalización (si no sabes cómo trabajar con MySQL mira este tutorial):

create table tarjetas_credito(
  id bigint  unsigned auto_increment,
  numero text,
  ccv blob,
  primary key(id)
);

Estamos definiendo una tabla que guardará tarjetas de crédito.

En este caso el número estará en texto plano pero el CCV estará en BLOB, es decir, en modo binario para que soporte los valores encriptados. Si quieres cifrar más datos, agrégalos y define el tipo como BLOB.

Al insertar un registro vamos a llamar a aes_encrypt:

insert into tarjetas_credito
(numero, ccv)
values
("0123456789", aes_encrypt("123", "hunter2"));

En texto plano, el CCV es 123. Lo ciframos con la clave hunter2.

Si listamos el contenido de la tabla (o si un atacante la roba) veremos lo siguiente:

1 – Seleccionar y mostrar datos encriptados con AES en MySQL

Son datos raros, incluso la salida podría mostrarse extraña y con espacios extraños; esto es porque el texto ya está cifrado.

Para descifrar se invoca a aes_decrypt pasándole la misma clave con la que hicimos el cifrado, como primer argumento se indica el valor cifrado.

select numero, aes_decrypt(ccv, "hunter2") from tarjetas_credito;

Si indicamos una contraseña errónea, la función devuelve null la mayoría de veces, aunque podría devolver “basura” en algunas ocasiones, es decir, nunca confíes en que siempre devolverá null para claves erróneas:

2 – aes_decrypt devuelve null con contraseña incorrecta

En caso de indicar la clave correcta el dato se muestra en texto plano, es decir, descifrado:

3 – Descifrar con AES en MySQL

Así es como podemos cifrar y descifrar con AES en MySQL. Como lo dije, hay que mantener la clave en otro lugar.

No te confundas, para probar insertamos el dato 123 como CCV y lo ciframos con la clave hunter2.

Fue un ejemplo básico pero podemos adaptarlo a nuestras necesidades o agregarle más características (podríamos definir un alias a la columna) interactuando con la base de datos desde un lenguaje de programación.

Sobra mencionar que podemos hacer un update y todo tipo de consultas o modificaciones que hacemos normalmente.

aes_encrypt y aes_decrypt sin BLOB

Como lo dije, hay una alternativa a utilizar BLOB y es convertir los datos binarios a su representación hexadecimal al guardarlos; y hacer el proceso inverso al seleccionarlos.

La función que convierte un dato a hexadecimal es HEX, y la función que hace lo inverso es UNHEX.

Ahora se puede definir la tabla para que guarde un valor de tipo TEXT y no BLOB:

create table tarjetas_credito(
  id bigint  unsigned auto_increment,
  numero text,
  ccv text,
  primary key(id)
);

Al hacer la inserción ciframos con aes_encrypt pero el resultado lo pasamos a través de HEX y el resultado de ésta última invocación es el que se guarda:

insert into tarjetas_credito
(numero, ccv)
values
("0123456789", hex(aes_encrypt("123", "hunter2")));

Si recuperamos los datos ahora ya estarán como texto, pues tendrán su forma hexadecimal.

4 – Datos cifrados y representados de manera hexadecimal

Para descifrar los datos invocamos a aes_decrypt pero los datos cifrados serán el resultado de invocar a UNHEX:

select numero, aes_decrypt(unhex(ccv), "hunter2") from tarjetas_credito;
5 – Descifrar datos usando aes_decrypt y unhex

Eso sí, los datos hexadecimales ocupan más espacio, pero son legibles y portables. Además, no necesitamos declarar el tipo de dato BLOB.

Para terminar, dejo un enlace al manual de MySQL.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Ver comentarios

Entradas recientes

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

6 días hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

6 días hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

6 días hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

6 días hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

6 días hace

Solución: Apache – Server unable to read htaccess file

Ayer estaba editando unos archivos que son servidos con el servidor Apache y al visitarlos…

7 días hace

Esta web usa cookies.