IT学习者 | 站长学院 | 技术文档 | 成语 | 歇后语 | 桌面壁纸 | 天气预报 | 帝国时代 | 生日密码 | 代码收藏 | 厦门天气 | IP地址查询 | 生活百科

MD5加密的JavaScript实现

【 来源:网络 作者:佚名 更新时间:2006-09-27 | 字体:

  MD5加密,共分5步:详细内容大家可以查看http://www.itlearner.com/article/2006/3463.shtml

  (1) 补位
  MD5算法是对输入的数据进行补位,使得如果数据位长度LEN对512求余的结果是448。即数
  据扩展至K*512+448位。即K*64+56个字节,K为整数。补位操作始终要执行,即使数据长度LEN
  对512求余的结果已是448。
  具体补位操作:补一个1,然后补0至满足上述要求。总共最少要补一位,最多补512位。
  (2) 补数据长度
  用一个64位的数字表示数据的原始长度b,把b用两个32位数表示。那么只取B的低64位。
  当遇到b大于2^64这种极少遇到的情况时,这时,数据就被填补成长度为512位的倍数。也就是说,
  此时的数据长度是16个字(32位)的整数倍数。用M[0 ... N-1]表示此时的数据,其中的N是16
  的倍数。
  (3) 初始化MD缓冲器
  (4)处理位操作函数
  (5)16进制形式输出结果。
  OK,下面就开始用javascript实现MD5加密。
  首先,我们要思考一下为了实现以上五步,我们需要哪些功能函数。
  第一、补位、补数据长度需要,可以定义为Inital(str),其中str是需要加密的原始字符串,该函数输出处理完后的数组。
  第二、处理位操作的四个函数,FF、GG、HH、II需要定义。
  第三、最后输出时要用16进制输出,并且高位0不可省略。
  好了,首先写第一个Inital函数。
  function Inital(str)
  {
   var len = str.length,count=0,wordIndex = 0;
   var m = len + 8;
   var wordNum = (m - m%64)/64 + 1;
   wordNum = wordNum * 16;
   var WordByte = new Array(wordNum -1);
   for(count = 0; count < len; count++)
   {
   wordIndex = (count - (count%4))/4;
   WordByte[wordIndex] |= ( str.charCodeAt(count)<<((count%4)*8));
   }
   wordIndex = (count - (count%4))/4;
   WordByte[wordIndex] |= (0x80<<((count%4)/8));
   wordIndex++;
   while(wordIndex < wordNum - 2)
   {
   WordByte[wordIndex] =0;
   wordIndex++;
   }
   WordByte[wordNum - 2] = len <<3;
   WordByte[wordNum - 1] = len >> 29;
   return WordByte;
  }
  下面简单说明一下这个函数,因为最后2个32位是用原始字符串长度来填充的(不明白的先去看MD5算法描述!哪个地方有?-_-!文章开头的链接就是。)所以我们先把原始字符串长度 + 8,(64位就是8个字节,这样就是假设最后的2个32位已经补充好了)。然后把中间的第一位补1,其余补0即可。
  不过呢,这里要注意一下字符串的顺序,假如字符串"abc",那么他们一共占3*8=24位,其中a先进入数组,然后b左移8位后进入,c左移16位后进入,作后要补的1000000(16进制的0x80)左移24位后进入。
  好了,下面就要定义位操作函数FF、GG、HH、II
  这里要注意的是,我们要重新定义32位操作数的+的操作和移位操作。
  function F(x,y,z) { return (x & y) | ((~x) & z); }
  function G(x,y,z) { return (x & z) | (y & (~z)); }
  function H(x,y,z) { return (x ^ y ^ z); }
  function I(x,y,z) { return (y ^ (x | (~z))); }
  function ADD(x, y){ return (x+y)&0xFFFFFFFF; }
   function RotateLeft(lValue, iShiftBits)
   { return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits)); }
  function FF(a,b,c,d,x,s,ac)
  {
   a = ADD(a, ADD(ADD(F(b, c, d), x), ac));
   return ADD(RotateLeft(a, s), b);
  }
  function GG(a,b,c,d,x,s,ac)
  {
   a = ADD(a, ADD(ADD(G(b, c, d), x), ac));
   return ADD(RotateLeft(a, s), b);
  }
  function HH(a,b,c,d,x,s,ac)
  {
   a = ADD(a, ADD(ADD(H(b, c, d), x), ac));
   return ADD(RotateLeft(a, s), b);
  }
  function II(a,b,c,d,x,s,ac) {
   a = ADD(a, ADD(ADD(I(b, c, d), x), ac));
   return ADD(RotateLeft(a, s), b);
  }
  说明一下FF(a,b,c,d,x,s,ac) 其实就是a = a + F(b, c, d) + x +ac;然后返回(a<<s) + b;只不过这里的+要用我们自己定义的加,就是mod 2^32后的结果,<<也是我们自己定义的左移。很容易理解的。
  下面就是输出16进制数的函数了
  function Word2Hex(str)
  {
   var hexValue = "",temp_str="";
   var i = 0,lByte;
   for(; i < 4; i++)
   {
   lByte = (str>>(i*8))& 0xFF;
   temp_str = "0" + lByte.toString(16);
   hexValue += temp_str.substr(temp_str.length - 2, 2);
   }
   return hexValue;
  }
  这个函数就是为了防止漏掉0而设的。
  好了,最后的就是主要的函数MD5(str)了。
  function MD55(str)
  {
   var smessage =new Array();
   // step 1 and 2:补位、补数据长度
   smessage = Inital(str);
   var i = 0,j =0;
   var a, b, c, d;
   // step 3 初始化位操作数
   a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
   // step 4位处理
   for(i = 0; i< smessage.length; i+=16)
   {
   AA = a;
   BB = b;
   CC = c;
   DD = d;
   for(j = 0; j < 4; j++)
   {
   a = FF(a, b, c, d, smessage[i + 4*j+0], SS[0], TT[4*j+0]);
   d = FF(d, a, b, c, smessage[i + 4*j+1], SS[1], TT[4*j+1]);
   c = FF(c, d, a, b, smessage[i + 4*j+2], SS[2], TT[4*j+2]);
   b = FF(b, c, d, a, smessage[i + 4*j+3], SS[3], TT[4*j+3]);
   }
   for(j = 0; j < 4; j++)
   {
   a = GG(a, b, c, d, smessage[i + Rotal[4*j+0]], SS[4],TT[16+4*j+0]);
   d = GG(d, a, b, c, smessage[i + Rotal[4*j+1]], SS[5],TT[16+4*j+1]);
   c = GG(c, d, a, b, smessage[i + Rotal[4*j+2]], SS[6],TT[16+4*j+2]);
   b = GG(b, c, d, a, smessage[i + Rotal[4*j+3]], SS[7],TT[16+4*j+3]);
   }
   for(j = 0; j < 4; j++)
   {
   a = HH(a, b, c, d, smessage[i + Rotal[16+4*j+0]], SS[8], TT[32+4*j+0]);
   d = HH(d, a, b, c, smessage[i + Rotal[16+4*j+1]], SS[9], TT[32+4*j+1]);
   c = HH(c, d, a, b, smessage[i + Rotal[16+4*j+2]], SS[10], TT[32+4*j+2]);
   b = HH(b, c, d, a, smessage[i + Rotal[16+4*j+3]], SS[11], TT[32+4*j+3]);
   }
   for(j= 0; j < 4; j++)
   {
   a = II(a, b, c, d, smessage[i + Rotal[4*j+32]], SS[12], TT[48+4*j+0]);
   d = II(d, a, b, c, smessage[i + Rotal[4*j+33]], SS[13], TT[48+4*j+1]);
   c = II(c, d, a, b, smessage[i + Rotal[4*j+34]], SS[14], TT[48+4*j+2]);
   b = II(b, c, d, a, smessage[i + Rotal[4*j+35]], SS[15], TT[48+4*j+3]);
   }
   a = ADD(a, AA);
   b = ADD(b, BB);
   c = ADD(c, CC);
   d = ADD(d, DD);
   }
   // step5
   var lResult = Word2Hex(a)+Word2Hex(b)+Word2Hex(c)+Word2Hex(d);
   document.message.test1.value = lResult.toLowerCase();
  }
  大家可以看到里面用了Rotal[]、SS[]、TT[]数组,其中Rotal[]是定义每次smessage移位数的,不明白的看看MD5算法描述。
  var AA = 0x67452301, BB = 0xEFCDAB89, CC = 0x98BADCFE, DD = 0x10325476;
  var SS = [7, 12, 17, 22, // step1
   5, 9, 14, 20, // step2
   4, 11, 16, 23,// step3
   6, 10, 15, 21];// step4
  var TT = [0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d, 0x2441453,0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085, 0x4881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391];
  var Rotal = [1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8,13, 2, 7,12,
   5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
   0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9];
  OK了,大功告成。这里再提供几组测试数据:
  MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
  MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
  MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
  MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
  MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
  MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
  d174ab98d277d9f5a5611c2c9f419d9f
  MD5 ("123456789012345678901234567890123456789012345678901234567890123456
  78901234567890") = 57edf4a22be3c955ac49da2e2107b67a

  • 转载请注明来源:IT学习者 网址:http://www.itlearner.com/ 向您的朋友推荐此文章
  • 文章关键词:  MD5 
  • 特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系我们,我们会尽快予以更正。
RSS订阅
  • 抓虾
  • google reader
  • 鲜果
  • QQ邮箱

音乐
犯贱 月光 包容 想你了 甩葱歌 黄梅戏 爱情错觉 星月神话 这就是爱 最幸福的人 爱笑的眼睛 321对不起 你不知道的事 看透爱情看透你 你还欠我一个拥抱
忐忑 爱过 浮夸 猜不透 洛丽塔 错的人 爱情买卖 和平分手 等你爱我 没那么简单 我的心好冷 姑娘我爱你 在回忆中死去 我的爱情不见了 你在我心中是最美
她说 偏爱 素颜 错错错 走天涯 套马杆 断桥残雪 爱是你我 郎的诱惑 客官不可以 我要去西藏 我的好兄弟 哥只是个传说 情歌没有告诉你 我和草原有个约定
天真 王妃 小三 爱琴海 要抱抱 单身歌 埋葬冬天 给力青春 荷塘月色 最好不相见 最炫民族风 新贵妃醉酒 贝多芬的悲伤 大笑江湖主题曲 给我一个理由忘记
加入收藏留言建议ASP探针PHP探针站长Enjoy的BlogAboutDomain
© 2010 IT学习者 - itlearner.com
RunTime:440.72ms