3 Ejercicios Para Encriptar y Desencriptar Datos en MySQL

Empezaremos con este post con el primero de tres ejercicios que consistirán en:

  1. La base de datos y un formulario para guardar claves encriptadas (en este artículo)
  2. Un formulario para validar los datos de un visitante
  3. Un formulario de emergencia para os usuarios que olvidaron su contraseña personal

Si deseas recibir las siguientes publicaciones en tu bandeja de correo anótate en el formulario a la derecha “Suscripción por correo electrónico”, o también podrías sindicar este blog con la dirección de nuestros feed Pulgar hacia arriba.

El ejercicio esta preparado para quienes tengan conocimientos intermedios de PHP (base de datos), del uso de phpMyAdmin y HTML5, trataré de mantener la explicación lo más sencilla posible.

La base de datos

Ingresamos a phpMyAdmin para diseñar nuestra base de datos (la nombraré ‘datos’), para no complicarnos el ejercicio y centrarnos en lo que nos interesa agregamos la tabla ‘usuarios’ con la siguiente estructura (5 campos):

Campo Atributos
idusuario entero, PK, auto_incremental
nombres varchar de 50 caracteres (en realidad pediremos nombre y apellido)
nick varchar de 50 caracteres, índice único (para impedir dos usuarios con el mismo alias)
clave varchar de 50 caracteres
clavex longtext (es para guardar la clave encriptada)

Una vista de mi phpMyAdmin:

Vista en phpMyAdmin de la estructura de la tabla 'usuarios'

Vista en phpMyAdmin de la estructura de la tabla ‘usuarios’

Y para quienes prefieren insertar instrucciones de comando a continuación las líneas del script al generar un backup de la BD:

— phpMyAdmin SQL Dump
— version 3.5.1
http://www.phpmyadmin.net
— Servidor: localhost
— Tiempo de generación: 05-10-2013 a las 10:49:13
— Versión del servidor: 5.5.24-log
— Versión de PHP: 5.3.13

SET SQL_MODE=”NO_AUTO_VALUE_ON_ZERO”;
SET time_zone = “+00:00”;

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
— Base de datos: `datos`

— ——————————————————–

— Estructura de tabla para la tabla `usuarios`

CREATE TABLE IF NOT EXISTS `usuarios` (
`idusuario` int(11) NOT NULL AUTO_INCREMENT,
`nombres` varchar(50) NOT NULL,
`nick` varchar(50) NOT NULL,
`clave` varchar(50) NOT NULL,
`clavex` longtext NOT NULL,
PRIMARY KEY (`idusuario`),
UNIQUE KEY `nick` (`nick`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

Sobre la encriptación de cadenas

No voy a extenderme en este punto sobre el que hay mucha y diversa información, me basaré en el sitio en español de PHP.net sobre funciones de hash, y de forma particular usaré la función hash_hmac(), posiblemente alguién me corrija sobre una mejor opción y saldré ganando Sonrisa.

¿Cómo saber si tu servidor soporta esta u otras cadenas hash? Carga phpinfo(), si no hay un acceso rápido crea una página en tu servidor con extensión php:

<?php echo phpinfo(); ?>

Carga esta página en tu navegador y busca la cadena ‘hash’, creo que todos los navegadores reconocen la combinación Ctrl + F, encontrarás este bloque:

Vista de los valores Hash en el servidor

Vista de los valores Hash en el servidor

La primera fila está en ‘enabled’ y significa que si soporta hash, la segunda fila muestra todas las funciones hash que están soportadas.

La función hash_hmac() requiere al menos de 3 parámetros (tipo cadena) en este orden:

  1. El algoritmo de cifrado que se va a usar, usaré en este ejercicio sha512, que en lo personal me parece bastante seguro (recordemos que la seguridad está en una serie de buenas prácticas y no solamente en encriptar).
  2. La cadena a cifrar
  3. Otra cadena que se usará en el algoritmo para encriptar la cadena 2 (usaré ‘primeraweb’).
  4. Opcionalmente un valor booleano, al omitirlo permanece en FALSE y la salida estará en valor hexadecimal en minúsculas.

Otro dato importante es que la cadena encriptada no podrá ser des-encriptada, en realidad lo que haremos en el segundo ejercicio es comparar dos cadenas encriptadas.

El formulario

Ahora el formulario en donde se registrará el nuevo usuario, solicitaremos su nombre y apellido, su nombre de usuario y su contraseña, en la pagina encripta1.php, las excusas del caso, omitiré las mayorías de las etiquetas para ir directamente al formulario:

<header>
<h1>Formulario de registro</h1>
</header>
<form name=”f1″ action=”encripta2.php” method=”post”>
Nombre y apellido<input type=”text” name=”nombres” placeholder=”Su nombre y apellido” autofocus required />
<br />
Nombre de usuario<input type=”text” name=”nick” placeholder=”Nombre de usuario” required />
<br />
Contrase&ntilde;a<input type=”password” name=”clave” required />
<br />
<input type=”submit” value=”Registrar mis datos” />
</form>

Nota: Si van a copiar y pegar es muy probable que tendrán que corregir las comillas.

Al cargar en el navegador tendremos esto (el navegador de Microsoft 8 y anteriores no sirven para HTML5):

El formulario en el navegador

El formulario en el navegador

En el action del formulario indicamos que los datos se enviarán a ‘encripta2.php’, allí procesaremos los datos encriptando la clave y almacenado en la BD, nuevamente iré directo a la implementación que nos interesa:

Recuperando datos del formulario y encriptando

Recuperando datos del formulario y encriptando

Este bloque termina imprimiendo la cadena encriptada (tranquilos, aún no hemos terminado) compuesta de dígitos hexadecimal en minúsculas, continuemos, puesto que solo lo coloqué para una prueba quitaré esa última línea.

Conexión a la BD, la cadena SQL con la instrucción Insert

Conexión a la BD, la cadena SQL con la instrucción Insert

Nos conectamos al servidor MySQL con ‘mysqli_connect()’ y preparamos en la variable $cadena_sql nuestra instrucción Insert para guardar los nuevos datos, quité las barras a la última línea para imprimir la instrucción SQL.

Condicional para evaluar si la operación tuvo éxito

Condicional para evaluar si la operación tuvo éxito

Ejecutamos la consulta con ‘mysqli_query()’, si la consulta de ejecuta devolverá un entero mayor a cero, es el número de registros afectados (en este caso se insertó un solo registro), si la operación fracasa se devuelve cero. Para eso usamos la estructura ‘if’ y mostramos un mensaje según la tarea tuvo éxito o no.

Con ‘mysqli_close()’ cerramos el recurso de conexión, el código completo de esta página es (nuevamente voy directo a lo que nos interesa):

<header>
<h1>Registrando sus datos</h1>
</header>
<?php
$nombres = $_POST[“nombres”];
$nick = $_POST[“nick”];
$clave = $_POST[“clave”];
//Encriptamos la clave ingresada y la almacenamos en $clavex
$secret = “primeraweb”;
$clavex = hash_hmac(“sha512”, $clave, $secret);
//Conectando a la BD
$servidor = “localhost”;
$usuario = “root”;
$pass = “”;
$bd = “datos”;
$cone = mysqli_connect($servidor,$usuario, $pass, $bd)or die(mysql_error());
$cadena_sql = sprintf(“Insert Into usuarios Values(null, ‘%s’, ‘%s’, ‘%s’, ‘%s’)”, $nombres, $nick, $clave, $clavex);
//echo $cadena_sql;
$x = mysqli_query($cone, $cadena_sql);
if($x > 0){
echo “Sus datos han sido guardado, ya est&aacute;s registrado🙂.”;
}else{
echo “¡Oops! Hubieron problemas, sus datos no pudieron registrarse.”;
}
mysqli_close($cone);
?>
<footer>
<p><a href=”encripta1.php”>Volver</a></p>
</footer>

Carga tu formulario, ingresa los datos y ve a revisar los datos de tu tabla en phpMyAdmin:

El registro fue insertado en la BD

El registro fue insertado en la BD

¡Y ya tenemos nuestro primer registro guardado! Y con esto terminamos nuestro primer ejercicio, no olviden suscribirse arriba a la derecha para los siguientes ejercicios ¡Buen fin de semana! Fiesta


Versión para imprimir en Google Drive de este artículo

11 responses to this post.

  1. Posted by alejo on 25/08/2014 at 901

    me gustaria hacer una caja de comentario justo como este da tengo diseño pero ala ves tener la oportunidad de montar fotos.. me podrias ayudar ya tengo la base de datos. conexion xamm.

    Responder

    • Saludos: Ese sería un buen ejercicio para un próximo artículo, pero te voy adelantando una idea sencilla. Si entiendo bien deseas cargar una foto de acuerdo al usuario que se halla autenticado (foto de perfil), en la BD en el campo ‘foto’ en vez de guardar la foto guardamos el nombre de archivo de la imagen (por ejemplo: user1.jpg), extraemos ese nombre en $datos[“foto”] y luego lo cargas a la página así:
      <?php
      $dir_img = "images/fotos/";
      echo "";
      ?>

      Espero te de una idea de la solución, esto se podría mejorar, pero solo trato de dar una idea general de como resolverlo🙂

      Responder

  2. Buen post amigo! Gracias por el aporte!😉

    (Ps: Has pensado migrar tu conexión a BD usando la clase PDO? Es relativamente nueva y es mas segura! Saludos!)

    Responder

  3. Posted by eldi on 07/05/2014 at 347

    Notice: Undefined index: nombres in C:\xampp\htdocs\haber\encripta1.php on line 19

    Notice: Undefined index: nick in C:\xampp\htdocs\haber\encripta1.php on line 20

    Notice: Undefined index: clave in C:\xampp\htdocs\haber\encripta1.php on line 21

    Responder

    • Siento mucho la demora Eldi, quizá ya diste con la solución, en todo caso, el mensaje indica a un dato no definido y lo más probable es que se trate de un problema con mayúsculas de minúsculas y mayúsculas (PHP es Case Sensitive), en todo caso vuelve a comunicarte con nosotros con otro comentario ¡Buen día!

      Responder

  4. oye tengo una duda, ammm no me guarda datos en la BD y no marca errores en el php, he intentado un par de cosas pero nada…

    Responder

    • Saludos Yandelrevolution, lamentamos la demora en responder, quizá ya diste con la solución, en todo caso lo más probable sea un error con los nombres de objetos en la BD y/o una de las cadenas SQL. O vuelve a contactarno con otro comentario ¡Buen día!

      Responder

  5. Posted by dary on 28/02/2014 at 1950

    es muy bueno pero como se hace el formulario

    Responder

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

A %d blogueros les gusta esto: