1 .
El algoritmo MD5
2 .
El formulario de Login
3 .
El script en PHP3
Artículo cedido por La página de Alfredo Reino.
El algoritmo MD5
El algoritmo MD5 es una funcion de cifrado tipo hash que
acepta una cadena de texto como entrada, y devuelve un numero de 128 bits. Las
ventajas de este tipo de algoritmos son la imposibilidad (computacional) de
reconstruir la cadena original a partir del resultado, y tambien la
imposibilidad de encontrar dos cadenas de texto que generen el mismo resultado.
Esto nos permite usar el algoritmo para transmitir contraseñas a traves de
un medio inseguro. Simplemente se cifra la contraseña, y se envia de forma
cifrada. En el punto de destino, para comprobar si el password es correcto, se
cifra de la misma manera y se comparan las formas cifradas.
El ejemplo que vamos a ver ahora, se implementa un sistema de formulario
de login y un script hecho en PHP3 que comprueba su validez.
Para ello, utilizamos la implementación de
MD5 en JavaScript de
Paul Johnston.
El formulario de Login
El siguiente documento en HTML contiene un formulario en el que el usuario
introduce su nombre de usuario y una contraseña. Cuando se pulsa el botón de
enviar, se añade al password un numero aleatorio, y todo ello se cifra usando
el algoritmo MD5.
A continuación, el numero aleatorio, y el resultado del MD5, se introducen
en elementos tipo "Hidden" en el formulario, y se envia todo a un
script escrito en PHP3 que verifica el acceso.
Formulario de login
<html><head><title></title>
<script language="JavaScript" src="md5.js"></script>
<script language="JavaScript">
numero = Math.random().toString();
function calculaMD5() {
var pw = document.forms["login"].elements["password"].value
pw += numero
return calcMD5(pw)
}
function enviaMD5(hash) {
document.forms["login"].elements["cifrado"].value = hash;
document.forms["login"].elements["numero"].value = numero;
document.forms["login"].submit();
}
</script>
</head>
<body>
<form action="auth.php3" method="POST" name="login">
Usuario: <input type="Text" name="usuario"><br>
Password: <input type="Password" name="password"><br>
<input type="Hidden" name="cifrado" value="">
<input type="Hidden" name="numero" value="">
<input type="Submit" value=" Login " onClick="enviaMD5(calculaMD5())">
</form>
</body></html>
El script en PHP3
PHP3 es un lenguaje de server-side scripting, como pueda
serlo el ASP, ColdFusion, etc. En este ejemplo se ha usado PHP3 porque ya lleva
una implementación del algoritmo MD5. Además, PHP3 es gratuito y open source.
Para más información, lo mejor es visitar
http://www.php.net/
Igualmente se podría haber utilizado ASP, utilizando la misma
implementación del MD5 que vimos antes, y escribiendo el script en JSCript.
Básicamente, el script extrae el password para el
usuario correspondiente (la función
passwordUsuario(), no está detallada en este
texto). A continuación, le añade el número aleatorio que recibe del formulario,
aplica el algoritmo MD5, y lo compara con el valor del password cifrado que
recibe del formulario.
Instalación de Apache/Php
<html><head><title></title></head>
<body>
<?
$password = passwordUsuario($usuario);
$serverpassword = strtolower(md5($password.$numero));
$clientpassword = strtolower($cifrado);
if ($serverpassword==$clientpassword)
{ print "<p>Correcto!"; }
else
{ print "<p>Acceso denegado!"; }
?>
</body></html>
Últimos comentarios
Últimos 5 comentarios
Para Luis (23/11/2007)
Por
Creo que es una vergüenza que alguien que parece de seguridad y que seguro que aprecia la informática diga: \\\"dejad de reinventar la rueda\\\". Si por algo la informática es tan rica hoy en dia es justo por \\\"reinventar la rueda\\\". Si tienes conocimiento de la evolución de la informática, sabrá que han surgido lenguajes como php, java habiendo cgi + C, o C respectivamente. \\\"Reinventaron la rueda\\\", pero haciendola válida para todos los coches y que se pudiera trabajar con ella más fácilmente.
Bien, dicho esto, solo apuntar que este script no sirve de nada porque un sniffer tendria los datos del hash y del numero, con lo que no te sirve.
Aqui el proposito es lograr una conexion segura sin htpps (claro que es lo ideal, pero paga tu eso).
Desde luego enviar la contraseña encriptada en md5 en un gran paso para que un sniffer no sepa la contraseña original, sino solo el hash.
Ahora, lo del numero es una tonteria porque un sniffer tambien te va a coger el numero. Y coge y envia el has con el numero ese y listo.
La cuestion seria obligar al que envia la información a usar un numero en la codificación. Asi, si un sniffer lo intenta, el servidor no le hará caso ya que el numero que le manda el usuario no es el numero que el servidor queria.
El problema de esto seria que habria que almacenar los numeros en alguna base de datos (mysql), y luego borrarlos. Habria que asociarlo con una id o con su ip, da lo mismo. La cuestion es que el servidor imponga un numero al azar.
Luis, este metodo que progongo supongo que si que es seguro. El sniffer solo tiene un hash o varios hash con un numero que el no sabe cual es. Si esto lo hacemos con numero del 1 al 10000 o mas, tendria que almacenar cientos de hashes y hacerlo en el tiempo que se está autentificando el usuario.
Es decir, que estamos ante un sistema seguro!
Pequeña gran ignorancia (12/11/2007)
Por
Tu respuesta titulada \"pequeña gran contradición\" no es tal, y sólo es fruto de no saber cómo funcionan las funciones hash de una sola vía.
Lo que el autor ha querido decir con eso es que, conociendo un resumen criptográfico (hash) de una cadena, generar otra que tenga el mismo resumen (colisión) es difícil. Y dicha dificultad reside en la cantidad de hashes diferentes que puede generar la función, que en el caso de MD5 es de dos elevado a 128. Si una persona conoce un resumen criptográfico y quisiera conocer cuál es la cadena que ha dado lugar a ese hash, necesitaría en el peor de los casos 2 elevado a 128 intentos para conseguirlo peeeero, eso no le garantiza obtener la misma cadena (lo cual es casi imposible porque es de una posibilidad frente a infinito) sino que obtendrá otra cadena que produce el mismo hash. No obstante, a efectos de la autenticación sería válido ya que el servidor se basa en el hash obtenido, no en la cadena que lo ha generado.
En resumidas cuentas: El autor ha escrito mal el texto al hablar sobre la \"imposibilidad de encontrar dos cadenas de texto que generen el mismo resultado\". Sí que se puede, y el caso peor está calculado. Lo que sucede es que es muy difícil (cada día menos debido a los ordenadores más rapidos). Por otro lado, cometes un error al tragarte este pastiche sobre autenticación y seguridad.
Pequeña gran contradiccion (25/10/2007)
Por
Hola, me parece bárbaro el artículo y muy bueno el ejemplo, pero me gustaría que me expliques un poco la parte en que escribes:
-“ y también la imposibilidad de encontrar dos cadenas de texto que generen el mismo resultado.”
Te contradices con:
-“ para comprobar si el password es correcto, se cifra de la misma manera y se comparan las formas cifradas.”
¿Si es imposible que de dos cadenas de texto se generen el mismo resultado, como hago para comparar la clave enviada y la que ya esta almacenada en el host?
¿ah? L
Saludos.
Es una tontería de método (17/10/2007)
Por
En respuesta a Loksly , tu solución es igual de inútil. Da lo mismo que el nº aleatorio se genere en el cliente o en el servidor. La cuestión es que es enviado y puede ser interceptado por un tercero que esté escuchando la red. Luego sólo tiene que repetir lo que tenía previsto hacer el cliente y hacerse pasar por él.
Mirad (y esto va para todos), las técnicas basadas en cifrar simétricamente a base de secretos, en donde dichos secretos viajan por la red, no tienen sentido.
Toda esta tontería de usar funciones hash en el lado del cliente no protege contra nada. El propio protocolo HTTP incorpora la posibilidad de usar MD5 para cifrar los passwords en el navegador (la famosa \"autenticación digest\"). Y en la especificación se deja claro que ese método es una medida de seguridad no confiable.
Si realmente queréis seguridad dejad de reinventar la rueda (y lo que es peor, sin saber) y centraos en los certificados digitales con su correspondiente respaldo de terceros (Verisign y cia). El resto son ganas de perder el tiempo y, lo que es peor, de crear una falsa imagen de seguridad.
Falsa seguridad... (22/08/2007)
Por
No tiene ningún sentido utilizar este sistema, pues no protege contra reenvío. Sería mejor que el número aleatorio se enviase desde el servidor, se almacenase en una variable $_COOKIE. Entonces en el lado del cliente se concatenaría el número aleatorio con el password y se enviaría. En el lado del servidor se recuperaría la variable "número aleatorio" almacenada en el array $_COOKIE y se simularía el proceso realizado en el cliente. Esta comprobación sería mucho más segura que la mostrada por el artículo.