MD5加密的算法和javascript實現MD5加密源碼

今天突然想看下MD5加密的原理,於是在網上找了一些算法。

資料:


算法描述  
 
對md5算法簡要的敘述可以爲:md5以512位分組來處理輸入的信息,且每一分組又被劃分爲16個32位子分組,經過了一系列的處理後,算法的輸出由四個32位分組組成,將這四個32位分組級聯後將生成一個128位散列值。

在 md5算法中,首先需要對信息進行填充,使其字節長度對512求餘的結果等於448。因此,信息的字節長度(bits length)將被擴展至n*512+448,即n*64+56個字節(bytes),n爲一個正整數。填充的方法如下,在信息的後面填充一個1和無數個 0,直到滿足上面的條件時才停止用0對信息的填充。然後,在在這個結果後面附加一個以64位黑吧表示的填充前信息長度。經過這兩步的處理,現在的信息字節長度=n*512+448+64=(n+1)*512,即長度恰好是512的整數倍。這樣做的原因是爲滿足後面處理中對信息長度的要求。  
 
md5中有四個32位被稱作鏈接變量(chaining variable)的整數參數,他們分別爲:a=0x01234567,b=0x89abcdef,c=0xfedcba98,d=0x76543210。 

當設置好這四個鏈接變量後,就開始進入算法的四輪循環運算。循環的次數是信息中512位信息分組的數目。  
 
將上面四個鏈接變量複製到另外四個變量中:a到a,b到b,c到c,d到d。

主循環有四輪(md4只有三輪),每輪循環都很相似。第一輪進行16次操作。每次操作對a、b、c和d中的其中三個作一次非線性函數運算,然後將所得結果加上第四個變量,文本的一個子分組和一個常數。再將所得結果向右環移一個不定的數,並加上a、b、c或d中之一。最後用該結果取代a、b、c或d中之一。  
以一下是每次操作中用到的四個非線性函數(每輪一個)。   
f(x,y,z) =(x&y)|((~x)&z)  g(x,y,z) =(x&z)|(y&(~z))  h(x,y,z) =x^y^z  i(x,y,z)=y^(x|(~z))  
(&是與,|是或,~是非,^是異或) 這四個函數的說明:如果x、y和z的對應位是獨立和均勻的,那麼結果的每一位也應是獨立和均勻的。  
f是一個逐位運算的函數。即,如果x,那麼y,否則z。函數h是逐位奇偶操作符。   
假設mj表示消息的第j個子分組(從0到15),<<  
ff(a,b,c,d,mj,s,ti) 表示a=b+((a+(f(b,c,d)+mj+ti)<< gg(a,b,c,d,mj,s,ti)表示a=b+((a+(g(b,c,d)+mj+ti)<< hh(a,b,c,d,mj,s,ti)表示a=b+((a+(h(b,c,d)+mj+ti)<< ii(a,b,c,d,mj,s,ti)表示a=b+((a+(i(b,c,d)+mj+ti)<<  這四輪(64步)是: 

第一輪   
ff(a,b,c,d,m0,7,0xd76aa478)  ff(d,a,b,c,m1,12,0xe8c7b756)  ff(c,d,a,b,m2,17,0x242070db)  ff(b,c,d,a,m3,22,0xc1bdceee)  ff(a,b,c,d,m4,7,0xf57c0faf) ff(d,a,b,c,m5,12,0x4787c62a)  ff(c,d,a,b,m6,17,0xa8304613)  ff(b,c,d,a,m7,22,0xfd469501)  ff(a,b,c,d,m8,7,0x698098d8)  ff(d,a,b,c,m9,12,0x8b44f7af)  ff(c,d,a,b,m10,17,0xffff5bb1)  ff(b,c,d,a,m11,22,0x895cd7be)  ff(a,b,c,d,m12,7,0x6b901122)  ff(d,a,b,c,m13,12,0xfd987193)  ff(c,d,a,b,m14,17,0xa679438e)  ff(b,c,d,a,m15,22,0x49b40821) 

第二輪   
gg(a,b,c,d,m1,5,0xf61e2562)  gg(d,a,b,c,m6,9,0xc040b340)  gg(c,d,a,b,m11,14,0x265e5a51)  gg(b,c,d,a,m0,20,0xe9b6c7aa)  gg(a,b,c,d,m5,5,0xd62f105d)  gg(d,a,b,c,m10,9,0x02441453)  gg(c,d,a,b,m15,14,0xd8a1e681)  gg(b,c,d,a,m4,20,0xe7d3fbc8)  gg(a,b,c,d,m9,5,0x21e1cde6)  gg(d,a,b,c,m14,9,0xc33707d6)  gg(c,d,a,b,m3,14,0xf4d50d87)  gg(b,c,d,a,m8,20,0x455a14ed)  gg(a,b,c,d,m13,5,0xa9e3e905)  gg(d,a,b,c,m2,9,0xfcefa3f8)  gg(c,d,a,b,m7,14,0x676f02d9)  gg(b,c,d,a,m12,20,0x8d2a4c8a)

第三輪  
 
hh(a,b,c,d,m5,4,0xfffa3942)  hh(d,a,b,c,m8,11,0x8771f681)  hh(c,d,a,b,m11,16,0x6d9d6122)  hh(b,c,d,a,m14,23,0xfde5380c)  hh(a,b,c,d,m1,4,0xa4beea44)  hh(d,a,b,c,m4,11,0x4bdecfa9)  hh(c,d,a,b,m7,16,0xf6bb4b60)  hh(b,c,d,a,m10,23,0xbebfbc70)  hh(a,b,c,d,m13,4,0x289b7ec6)  hh(d,a,b,c,m0,11,0xeaa127fa)  hh(c,d,a,b,m3,16,0xd4ef3085) hh(b,c,d,a,m6,23,0x04881d05)  hh(a,b,c,d,m9,4,0xd9d4d039)  hh(d,a,b,c,m12,11,0xe6db99e5)  hh(c,d,a,b,m15,16,0x1fa27cf8)  hh(b,c,d,a,m2,23,0xc4ac5665) 

第四輪  
 
ii(a,b,c,d,m0,6,0xf4292244)  ii(d,a,b,c,m7,10,0x432aff97)  ii(c,d,a,b,m14,15,0xab9423a7)  ii(b,c,d,a,m5,21,0xfc93a039)  ii(a,b,c,d,m12,6,0x655b59c3)  ii(d,a,b,c,m3,10,0x8f0ccc92)  ii(c,d,a,b,m10,15,0xffeff47d)  ii(b,c,d,a,m1,21,0x85845dd1)  ii(a,b,c,d,m8,6,0x6fa87e4f)  ii(d,a,b,c,m15,10,0xfe2ce6e0)  ii(c,d,a,b,m6,15,0xa3014314)  ii(b,c,d,a,m13,21,0x4e0811a1)  ii(a,b,c,d,m4,6,0xf7537e82)  ii(d,a,b,c,m11,10,0xbd3af235)  ii(c,d,a,b,m2,15,0x2ad7d2bb)  ii(b,c,d,a,m9,21,0xeb86d391)  

常數ti可以如下選擇:  
 
在第i步中,ti是4294967296*abs(sin(i))的整數部分,i的單位是弧度。(4294967296等於2的32次方)  
所有這些完成之後,將a、b、c、d分別加上a、b、c、d。然後用下一分組數據繼續運行算法,最後的輸出是a、b、c和d的級聯。  
 
當你按照我上面所說的方法實現md5算法以後,你可以用以下幾個信息對你做出來的程序作一個簡單的測試,看看程序有沒有錯誤。   
md5 ("") = d41d8cd98f00b204e9800998ecf8427e  md5 ("a") = 0cc175b9c0f1b6a831c399e269772661  
md5 ("abc") = 900150983cd24fb0d6963f7d28e17f72  
md5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0  
md5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b  md5 ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789") =  
d174ab98d277d9f5a5611c2c9f419d9f  
md5 ("123456789012345678901234567890123456789012345678901234567890123456789  01234567890") = 57edf4a22be3c955ac49da2e2107b67a  

 
如果你用上面的信息分別對你做的md5算法實例做測試,最後得出的結論和標準答案完全一樣,那我就要在這裏象你道一聲祝賀了。要知道,我的程序在第一次編譯成功的時候是沒有得出和上面相同的結果的。


javascrip代碼如下


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>md5加密</title>
</head>
<body>
<input id=test value=密碼區>
<input type=button value=md5 onClick="alert(hex_md5(test.value))">
<script>
var hexcase = 0;  
var b64pad  = "";
var chrsz   = 8; 
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function calcMD5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function md5_vm_test()
{
  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}


function core_md5(x, len)
{
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;
  
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;


  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;
    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
  }
  return Array(a, b, c, d);
  
}
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
function core_hmac_md5(key, data)
{
  var bkey = str2binl(key);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);


  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++) 
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }


  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  return core_md5(opad.concat(hash), 512 + 128);
}


function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}


function bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}


function str2binl(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
  return bin;
}


function binl2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
  }
  return str;
}


function binl2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}
</script>
</body>
</html>

我測試的結果


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章