Rutina para calcular MD5 en javascript

Tengo implementado un procedimiento para calcular el famoso hash MD5. El código lo libero con licencia LGPL y lo muestro a continuación.

// translate a N 32 bit number to a 8 char hex string
function hex(n){
var h= '0123456789abcdef', s= '';
for (var i= 4; i<32; i= i&4 ? i^4 : i+12)
s+= h.charAt(n>>i & 15);
return s;
}
// iterate function for md5
function cmn(a, b, c, d, e, f) {
return c+((a+= b+d+f) << e | a >>> 32-e);
}
// md5 function, input a string and returns a string
function md5(s){
var l, n= (l= s.length)+8 >> 6;
x= new Array(n= ++n << 4);
for (var i= 0; i<n;)
x[i++]= 0;
for (i= 0; i<l; i++)
x[i>>2]|= s.charCodeAt(i) << i%4*8;
x[i>>2]|= 0x80 << i%4*8;
x[n-2]= l*8;
var a= 0x67452301, b= 0xEFCDAB89, c= 0x98BADCFE,
d= 0x10325476, e=a, f=b, g=c, h=d;
for (i= 0; i < x.length;)
a= cmn(b&c|~b&d, a, b, x[i++],  7, 0xD76AA478),
d= cmn(a&b|~a&c, d, a, x[i++], 12, 0xE8C7B756),
c= cmn(d&a|~d&b, c, d, x[i++], 17, 606105819),
b= cmn(c&d|~c&a, b, c, x[i++], 22, 0xC1BDCEEE),
a= cmn(b&c|~b&d, a, b, x[i++],  7, 0xF57C0FAF),
d= cmn(a&b|~a&c, d, a, x[i++], 12, 0x4787C62A),
c= cmn(d&a|~d&b, c, d, x[i++], 17, 0xA8304613),
b= cmn(c&d|~c&a, b, c, x[i++], 22, -45705983),
a= cmn(b&c|~b&d, a, b, x[i++],  7, 0x698098D8),
d= cmn(a&b|~a&c, d, a, x[i++], 12, 0x8B44F7AF),
c= cmn(d&a|~d&b, c, d, x[i++], 17, -42063),
b= cmn(c&d|~c&a, b, c, x[i++], 22, 0x895CD7BE),
a= cmn(b&c|~b&d, a, b, x[i++],  7, 0x6B901122),
d= cmn(a&b|~a&c, d, a, x[i++], 12, -40341101),
c= cmn(d&a|~d&b, c, d, x[i++], 17, 0xA679438E),
b= cmn(c&d|~c&a, b, c, x[i++], 22, 0x49B40821),
a= cmn(b&d|c&~d, a, b, x[i-15], 5, 0xF61E2562),
d= cmn(a&c|b&~c, d, a, x[i-10], 9, 0xC040B340),
c= cmn(d&b|a&~b, c, d, x[i-5], 14, 643717713),
b= cmn(c&a|d&~a, b, c, x[i-16],20, 0xE9B6C7AA),
a= cmn(b&d|c&~d, a, b, x[i-11], 5, 0xD62F105D),
d= cmn(a&c|b&~c, d, a, x[i-6],  9, 38016083),
c= cmn(d&b|a&~b, c, d, x[i-1], 14, 0xD8A1E681),
b= cmn(c&a|d&~a, b, c, x[i-12],20, 0xE7D3FBC8),
a= cmn(b&d|c&~d, a, b, x[i-7],  5, 568446438),
d= cmn(a&c|b&~c, d, a, x[i-2],  9, 0xC33707D6),
c= cmn(d&b|a&~b, c, d, x[i-13],14, 0xF4D50D87),
b= cmn(c&a|d&~a, b, c, x[i-8], 20, 0x455A14ED),
a= cmn(b&d|c&~d, a, b, x[i-3], 5 , 0xA9E3E905),
d= cmn(a&c|b&~c, d, a, x[i-14], 9, -51403784),
c= cmn(d&b|a&~b, c, d, x[i-9], 14, 0x676F02D9),
b= cmn(c&a|d&~a, b, c, x[i-4], 20, 0x8D2A4C8A),
a= cmn(b^c^d, a, b, x[i-11], 4, -378558),
d= cmn(a^b^c, d, a, x[i-8], 11, 0x8771F681),
c= cmn(d^a^b, c, d, x[i-5], 16, 0x6D9D6122),
b= cmn(c^d^a, b, c, x[i-2], 23, -35309556),
a= cmn(b^c^d, a, b, x[i-15], 4, 0xA4BEEA44),
d= cmn(a^b^c, d, a, x[i-12], 11, 0x4BDECFA9),
c= cmn(d^a^b, c, d, x[i-9], 16, 0xF6BB4B60),
b= cmn(c^d^a, b, c, x[i-6], 23, 0xBEBFBC70),
a= cmn(b^c^d, a, b, x[i-3], 4, 681279174),
d= cmn(a^b^c, d, a, x[i-16], 11, 0xEAA127FA),
c= cmn(d^a^b, c, d, x[i-13], 16, 0xD4EF3085),
b= cmn(c^d^a, b, c, x[i-10], 23, 76029189),
a= cmn(b^c^d, a, b, x[i-7], 4, 0xD9D4D039),
d= cmn(a^b^c, d, a, x[i-4], 11, 0xE6DB99E5),
c= cmn(d^a^b, c, d, x[i-1], 16, 530742520),
b= cmn(c^d^a, b, c, x[i-14], 23, 0xC4AC5665),
a= cmn((b|~d)^c, a, b, x[i-16], 6, 0xF4292244),
d= cmn((a|~c)^b, d, a, x[i-9], 10, 0x432AFF97),
c= cmn((d|~b)^a, c, d, x[i-2], 15, 0xAB9423A7),
b= cmn((c|~a)^d, b, c, x[i-11], 21, -57434055),
a= cmn((b|~d)^c, a, b, x[i-4], 6, 0x655B59C3),
d= cmn((a|~c)^b, d, a, x[i-13], 10, 0x8F0CCC92),
c= cmn((d|~b)^a, c, d, x[i-6], 15, -1051523),
b= cmn((c|~a)^d, b, c, x[i-15], 21, 0x85845DD1),
a= cmn((b|~d)^c, a, b, x[i-8], 6, 0x6FA87E4F),
d= cmn((a|~c)^b, d, a, x[i-1], 10, -30611744),
c= cmn((d|~b)^a, c, d, x[i-10], 15, 0xA3014314),
b= cmn((c|~a)^d, b, c, x[i-3], 21, 0x4E0811A1),
a= cmn((b|~d)^c, a, b, x[i-12], 6, 0xF7537E82),
d= cmn((a|~c)^b, d, a, x[i-5], 10, 0xBD3AF235),
c= cmn((d|~b)^a, c, d, x[i-14], 15, 718787259),
b= cmn((c|~a)^d, b, c, x[i-7], 21, 0xEB86D391),
a+= e, e= a,
b+= f, f= b,
c+= g, g= c,
d+= h, h= d;
return hex(a) + hex(b) + hex(c) + hex(d);
}

Este algoritmo puede ser inseguro (hablando en términos criptográficos) depende cómo se use. No lo recomiendo ni como algoritmo resumen en firmas digitales, ni tampoco para guardar contraseñas encriptadas en una base de datos.

Sin embargo es útil para comprobar archivos corruptos o para hacer login en conexiones no seguras. Para esto último lo he usado yo. En otro artículo explicaré cómo implementar ésto con php en el lado del servidor.

2 Respuestas a este post.

  1. Por Luis el 08.05.2008 a las 16:23

    Hola Antonio, buen script.

    Pregunto, como podria utilizarse para calcular el md5 de un archivo? La duda viene porque estoy sopesando la idea de comparar el md5 de un archivo al momento de hacer el upload con javascript y una vez subido con php, de este modo comprobar que no hubo ningún error en el camino.
  2. Por admin el 19.05.2008 a las 01:40

    Hola Luis

    Desgraciadamente no existen forma de acceder al sistema de archivos desde javascript. En realidad se puede con adobe AIR para AJAX, aunque seguramente lo querrás para una página web y esto es para aplicaciones.

    Por motivos de seguridad, el protocolo de subida de archivos es bastante rígido. Tanto que hasta es casi imposible modificar gráficamente el aspecto del input type="file...

    En cambio una vez subido al servidor y desde php no habría problema, hay una función en php con el mismo nombre. Con un if (md5(file_get_contents(archivo))!='123abc...') die('error') te valdría.

Responder