Librería para usar MD5 y SHA 1 en Javascript

En fin, me he quedado sin ordenador el fin de semana… pero todavía me apaño para dejar una minientrada.

Hemos hablado ya en el pasado de criptografía y de algoritmos de hash e incluso de cómo usarlos en C o en Java así que hoy nos toca verlo desde otro ángulo. A la hora de usar estos algoritmos de resumen en una web, para almacenar una contraseña por ejemplo, nos podemos encontrar con la duda ¿encripto en el lado del servidor o en el del cliente? En fin, en el lado del servidor no tiene mucha ciencia ya que desde PHP 4 existen funciones MD5 y SHA1 de forma nativa. Pero ¿y si queremos hacerlo en el cliente?. Encriptar en el servidor implica que el mensaje viaje en texto plano desde el equipo hasta él. En cambio encriptando en el cliente esta ya saldrá encriptada del equipo.

Podría tirarme el moco y hacerme el pro copiando aquí un chorretón de código enorme, pero realmente os daré dos opciones:

  • PHP.js: Se trata de una librería libre de javascript que aporta a este lenguaje todas (o gran parte) de las existentes para PHP. Podéis descargarla desde la web oficial del proyecto, donde además podréis personalizar la librería eligiendo las funciones que os interesen (coged sólo lo justo, para aligerar la carga).
  • JSHASH: Esta otra , bajo licencia BSD, está en versión beta y se orienta totalmente al uso de  algoritmos de reducción (incluye además de las dos citadas sha256 y sha512). La recomiendan en varios blogs como muy fiable. Podéis descargarla de aquí, donde también hay tutoriales sobre su utilización.

En fin, con esto ya tenéis dos opciones para generar hashes con facilidad y sin romperos mucho la cabeza.

Funciones de resumen (MD5, SHA-1)

Aunque ya hablé de MD5 en este blog (con una entrada que hasta está referenciada en la wikipedia), no expliqué de todo el funcionamiento y la utilidad de las funciones de resumen, o funciones hash, y también conocidas como huellas de mensaje o huellas digitales. Se utilizan para crear una cadena de longitud fija o resumen de mensaje a partir de una cadena de entrada de longitud variable.

Este tipo de funciones han de cumplir una serie de condiciones para ser consideradas seguras:

  • No debe ser posible averiguar el mensaje de entrada basándose sólo en su resumen. Ha de ser una función irreversible de una sola dirección.
  • Dado un resumen debe ser imposible encontrar un mensaje que lo genere.
  • Debe ser computacionalmente imposible encontrar dos mensajes que generen el mismo resumen.

Es por esto por lo que a día de hoy se está dudando del futuro de MD5, dado que existen posibilidades de colisión (incumple el punto tres) que le harían vulnerable a un ataque de tipo cumpleaños.

SHA-1, al tener una longitud de clave mayor (160 bits frente a los 128 de MD5), es más robusto y resistente a ataques, si bien también se ha planteado que en un futuro próximo puede tornarse inseguro a ataques de fuerza bruta.

Las utilidades de estas funciones son múltiples y varias, entre otras almacenar contraseñas de forma segura (almacenando el hash en lugar del texto plano), la autenticación de entidades en un control de acceso, la identificación y comparación rápida de contenidos (por ejemplo en redes P2P),  o para proteger la integridad de los datos ya sea como firma digital o generando un checksum.

Como ejemplo, si probamos a encriptar la cadena pepito con MD5 y SHA-1 obtendremos estos resultados:

  • MD5: 32164702f8ffd2b418d780ff02371e4c
  • SHA-1: e04820372e7f2ebb2d76987433579219b11c2ba5

Ya véis que la segunda cadena/resumen es sensiblemente más larga.

En fin, las funciones hash son un elemento clave en la seguridad informática, siendo muy utilizadas tanto en UNIX como en Internet.

Encriptando en MD5 con java

Todavía no he buceado mucho en JavaSE7, pero que yo recuerde JSE6 no incluía ninguna función que encriptara en MD5, y a la hora de trabajar con contraseñas (a nivel de seguridad web, por ejemplo) este algoritmo es muy útil. Normalmente en mis desarrollos en PHP suelo encriptar en el cliente usando una función md5 en Javascript, pero en Java podréis hacerlo con el siguiente código. Se trata de una función que recibe una cadena y devuelve su hash md5.

Bueno, primero tendréis que incluir estas dos librerías:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

En todo caso, si usáis Eclipse o NetBeans para programar en Java ya os pedirá que importéis dichas librerías al añadir referencias a ellas en el código. La función es la siguiente:

        public static String cryptMD5(String textoPlano)
	{
		try
		{
		   private static final char[] HEXADECIMALES = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };

		   MessageDigest msgdgt = MessageDigest.getInstance("MD5");
		   byte[] bytes = msgdgt.digest(textoPlano.getBytes());
		   StringBuilder strCryptMD5 = new StringBuilder(2 * bytes.length);
		   for (int i = 0; i < bytes.length; i++)
		   {
		       int low = (int)(bytes[i] & 0x0f);
		       int high = (int)((bytes[i] & 0xf0) >> 4);
		       strCryptMD5.append(HEXADECIMALES[high]);
		       strCryptMD5.append(HEXADECIMALES[low]);
		   }
		   return strCryptMD5.toString();
		} catch (NoSuchAlgorithmException e) {
		   return null;
		}
	}

La he testeado y ha ido funcionando, así que creo que os puede hacer un buen servicio a la hora de trabajar con contraseñas de forma segura.