Creando un HASH de ida y vuelta con MD5 en php.

Pongamos un ejemplo: tengo un clásico listado de noticias y su respectivo detalle. En el listado propago el id de la noticia para saber cual levantar en el archivo de detalle (la típica noticias.php?id=1), pero que pasa si quiero proteger la identidad de dicho id? Puedo ofuscarlo pero no sería realmente una protección segura, o lo mejor, puedo hacer de éste un HASH pero no tendría vuelta (recordemos que un HASH no tiene vuelta) y en el caso de ser un id (un simple valor int) puedo usar brutal force para saber cual es el valor nativo con un simple for.
A continuación les mostraré que se puede generar un hash seguro, y no solo eso, sino que lo podré usar para comparar con el id real, aunque lo mejor es que será de manera simple.

No voy a explicar experiencias alternativas que he tenido con esto en este post, voy a ir al grano ejemplificando con php y mysql.
Supongamos que tenemos dos archivos, noticias_listados.php y noticias_detalles.php. En la primera tendré links del estilo:

<? While($rs = mysql_fetch_assoc( $r ) ){ ?>
<a href=”noticias_detalle.php?id=<?=$rs[‘id’]?>”><?=$rs[‘titulo’]?></a>
<? } ?>

Todo lo que necesitare para continuar es una key que será un simple string declarado en un variable que tendré en un archivo en común (puede ser el de la conexión a la base de datos):

$key = ‘cu4n70_m4s_c0mpl3j0_m3j05’;

No tiene que ser largo, pero si le podemos poner caracteres especiales como un #o o un &, %, /,;,(,),etc, como si fuera un password nuestro.

Una vez ésto, para imprimir haremos:

<? While($rs = mysql_fetch_assoc( $r ) ){ ?>
<a href=”noticias_detalle.php?id=<?=md5($key.$rs[‘id’])?>”><?=$rs[‘titulo’]?></a>
<?} ?>

Lo que hacemos acá es meter la key que solo nosotros conocemos concatenada del id y generar un HASH usando MD5 (generalmente no dará de 32 caracteres, 16 en modo binario). De ésta manera tendremos en pantalla de nuestro browser algo como:

<a href=”noticias_detalle.php?id=5141cg3c5fg31t03erc3brb0474t0530”>Esto es una noticia con su id HASEADO</a>

Perfecto, acá ya logramos tener un id totalmente camuflado, y no solo eso, sino que de manera segura!.

Ahora, en el detalle solíamos hacer algo como:

$sql = “Select * from noticias where id = ‘$id’ ”;

Y se preguntaran como hacemos para volver este string de 32 caracteres al valor numérico que necesitamos; y la respuesta es que NO lo haremos, sino que transformaremos del lado de mysql los id en conjunto con nuestra key al momento de comparar. El código es simple:

$sql = «Select * from noticias where MD5(concat(‘».$key.»‘,id)) = ‘$id'»;

Con eso tenemos resulesto nuestro problema, no mostramos más nuestros id y nadie sabe como trabajamos internamente, lo que nos da un poco más de seguridad.

Aclaro que los valores que usamos en los where (variable $id) es una variable seteada previamente con el GET[‘id’] y limpia de malas intenciones, y lo mismo con otras variables como ser por ejemplo $r. Es solo una idea de como implementar este método, cualquier consulta será bienvenida.

18 Responses to Creando un HASH de ida y vuelta con MD5 en php.

  1. GutemX dice:

    Muy buena manera!!, me gusto la manera en que lo resolves del lado de mysql, y leí que no es costoso para la base de datos.

  2. markshock dice:

    MMmmm… interesante… nunca me lo había planteado de esta manera… normalmente me da igual que vean el ID de una noticia.. pero para otras cosas (carritos de compra etc…) es interesante…

    😉

  3. Andres dice:

    Es muy buena, simple y efectiva…ideal para que no puedan ver contenidos que uno no quiere mostrar con solo cambiar el id por query string.
    También lo acabo de aplicar en el famoso «activar cuenta» al registrar, enviando al email un link con el id de esta manera.

    Gracias eh!

  4. nAcho dice:

    Es mas correcto y mas favorable para SEO reescribir las urls, con apache puedes usar mod_rewrite.
    La tecnica que utilizas para cifrar con md5, agregando un string concatenado, se llama «salting».

  5. nAcho dice:

    Ah, un detalle, el hashing es solo de ida. No se puede obtener el string original. Sin tener en cuenta, obviamente, ataques por fuerza bruta y demas.

    Saludos

  6. nicolaspar dice:

    Hola nAcho, no sabía el término “salting” y se agradese como todo comentario ;). En cuanto al hash de ida y vuelta lo sé y lo aclaro en el primer parrafo, es una manera «mentirosa de volverlo»…pero efectiva.

    Otra cosa, no creo que aplique en muchos casos para SEO como bien decís; creí que estaba claro que esta técnica es más que nada para proteger datos de manera segura y no para mostrar una linda url que es lo que necesita lograr un SEO man…son cosas diferentes.

  7. El Dueño dice:

    muy buen blog! le vas a dar continuación o murió??? saludos!

  8. nicolaspar dice:

    Seguramente si, cuando me haga de tiempos y vea que es interesante para escribir lo haré.

    Saludos y gracias 😉

  9. Walter dice:

    Hola, estoy intentando hacer que funcione, tengo un problema al hacer la comparacion, este es el codigo que le puse, pero no hace nada…

    $id_equipo=$_GET[‘id_equipo’];
    if (isset($id_equipo)){
    include(«conectar.php»);
    $link=Conectarse();
    $result = mysql_query(«DELETE FORM equipos WHERE MD5(concat(‘».$key.»‘,id_equipo)) = $id_equipo»,$link);
    header(«Location: administrador.php?equipos»);
    }

  10. nicolaspar dice:

    1- Nunca asignes variables directamente de POST/GET…
    2- Usá empty en lo posible (al menos a este ejemplo)
    3- Usá echo para ver que te imprime, entonces:

    $id_equipo=empty($_GET[‘id_equipo’]) ? » : $_GET[‘id_equipo’];
    if( !empty($id_equipo) ){
    include(”conectar.php”);
    $link=Conectarse();
    $sql = ”DELETE FORM equipos WHERE MD5(concat(‘”.$key.”’,id_equipo)) = ‘{$id_equipo}’”;
    echo $sql; exit; #Esto te mostrará tu query, el cual puedes probar directamente contra MYSQL usando Phpmyadmin, SqlYog, etcétera.
    mysql_query($sql,$link);
    header(”Location: administrador.php?equipos”);
    }

    Si $key+id_equipo generó el contenido $id_equipo debería funcionarte.

  11. jamesjara dice:

    very goodd!

    gracias mop

  12. Raul Garcia dice:

    y esto aplica tambien para que no se mire la url original en el codigo fuente????

  13. Benjamin Sañudo dice:

    no funciona.. no se porque pero no me funciona.. esto vale si el id de la tabla es numerico y AI

  14. Nicolás Pardo dice:

    Es indiferente, concat genera un único string concatenado.
    Y funcionar funciona, algo mal estás haciendo. Mira bien el código y su lógica y compréndelo.

  15. Simple y bueno el Script..

    Gracias.

  16. jonectron dice:

    buenisimo compadre!!!!

    gracias!!!! 😀

  17. Mr. M dice:

    Funciona excelente, me parece excelente la calidad de la información. Esperamos por más!

  18. If you have a bigger chip stack you can perform much more aggressively. If you find it thrilling you can purchase it and install on your desktop. But when we look at different platforms we see some thing else.

Deja un comentario