Cifrado y descifrado de datos en MySQL con AES y SHA
La protección de la información es un tema importante, y toma más relevancia cuando esta información se encuentra almacenada en la nube y es accesible desde Internet.
Una forma practica y eficiente de cifrar los datos para su almacenamiento en una base de datos y su posterior descifrado para tener acceso a los mismos es el uso de Advanced Encryption Standard (AES), que es un entandar de cifrado aprobado por la la Agencia de Seguridad Nacional de los Estados Unidos (NSA) para el cifrado de información no clasificada en 2005.
Este cifrado utiliza una Llave “KEY” para el cifrado, de tal forma que si no se conoce esta Llave no se podrá recuperar los datos originales.
Además para hacer más segura esta Llave se puede utilizar el Secure Hash Algorithm (SHA), lo que permitirá generar una llave HASH más segura que la cadena original.
Nota: AES_ENCRYPT() y AES_DECRYPT() fueron añadidas en la versión 4.0.2, y pueden considerarse como las funciones de cifrado y descifrado más seguras disponibles actualmente en MySQL.
NOTA: al cifrar los datos estos deben tener el tamaño suficiente para almacenar el valor y el cifrado, una forma fácil de calcular el tamaño del campo es usar alguna hoja de cálculo y usar la siguiente formula, donde longitud_de_la_cadena es el tamaño máximo del campo.
16 * (trunc(longitud_de_la_cadena / 16) + 1)
Ejemplo si el teléfono va a tener 10 números la formula sería así
16 * (trunc(10 / 16) + 1)
Y el resultado es 16, que sería el tamaño del campo para guardar un número telefónico de 10 dígitos.
1. Para entender y aplicar estos conceptos se crea la siguiente base de datos de prueba.
CREATE DATABASE base_cifrada DEFAULT CHARACTER SET latin1 COLLATE latin1_spanish_ci;
USE base_Cifrada;
CREATE TABLE tabla_cifrada(
id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
nombre VARCHAR(50),
telefono VARCHAR(16)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 COLLATE latin1_spanish_ci;
Nota: Como se puede ver la base de datos no tiene nada de especial, el proceso de cifrado y descifrado se realizará al insertar y seleccionar los datos.
2.- Ahora se insertaran los registros, y cada campo que se desee cifrar se hará utilizando el comando AES_ENCRYPT, que recibe como parámetros el valor a cifrar y la llave, en este caso para la llave se utiliza el comando SHA2 que recibe como parámetro la llave que se utilizara y el número de bits del HASH, de esta forma el valor será cifrado y se almacenará en la base de datos.
INSERT INTO tabla_cifrada(
nombre,
telefono
)
VALUES (
AES_ENCRYPT('María', SHA2('CLAVE',512)),
AES_ENCRYPT('7757512345', SHA2('CLAVE',512))
);
INSERT INTO tabla_cifrada(
nombre,
telefono
)
VALUES (
AES_ENCRYPT('José', SHA2('CLAVE',512)),
AES_ENCRYPT('7757523456', SHA2('CLAVE',512))
);
3.- Al consultar los registros almacenados se con la consulta SELECT * FROM tabla_cifrada; el resultado se ve como en la imagen siguiente.
4.- Para poder ver los valores originales se utiliza el comando CONVERT, con los siguientes parámetros:
a) El comando AES_DECRYPT, que se encarga de descifrar el valor almacenado, para esto necesita como parámetros el campo y la llave.
b) Como la llave se generó con SHA2 hay que volverlo a generar para poder tener la llave con la que se cifro el valor.
c) Con el comando USING UTF8 se convierte el valor binario a texto.
d) Utilizando AS se nombra el campo generado con el nombre que se desee, en este caso el mismo nombre del campo donde se guardo el valor.
SELECT
id,
CONVERT(AES_DECRYPT(nombre, SHA2('CLAVE',512)) USING utf8) AS nombre,
CONVERT(AES_DECRYPT(telefono, SHA2('CLAVE',512)) USING utf8) AS telefono
FROM
tabla_cifrada;
En la siguiente imagen se puede ver el procedimiento y el resultado, este paso se realiza por cada campo que se quiera descifrar.
Segunda forma
1.- Otra forma cifrar los datos si no se desea utilizar un HASH para la llave, se puede utilizar directamente como parámetro un valor Alfanumérico, tal como se muestra en el siguiente código.
INSERT INTO tabla_cifrada(
nombre,
telefono
)
VALUES (
AES_ENCRYPT('Maria', 'CLAVE'),
AES_ENCRYPT('7757512345', 'CLAVE')
);
2.- En la siguiente imagen se puede ver el resultado al hacer la consulta de los datos con SELECT * FROM tabla_cifrada;
3.- para descifrar el valor se utiliza AES_DECRYPT con el nombre del campo y la llave Alfanumérica.
SELECT
id,
CONVERT(AES_DECRYPT(nombre,'CLAVE') USING utf8) AS nombre,
CONVERT(AES_DECRYPT(telefono,'CLAVE') USING utf8) AS telefono
FROM
tabla_cifrada;
4.- En la siguiente imagen se muestra el resultado de seleccionar los datos convirtiéndolos previamente.
NOTAS
Una forma de no estar creando el HASH cada vez que se quiera cifrar o descifrar es crear una variable y posteriormente solo llamarla cuando sea necesario, tal como se muestra en el siguiente ejemplo.
SET @clave:=SHA2('CLAVE',512);
INSERT INTO table VALUES (1,AES_ENCRYPT('text',@clave));
Comentarios