MD5(單向散列算法)
的全稱是Message-Digest Algorithm 5(信息-摘要算法),經MD2、MD3和MD4發展而來。MD5算法的使用不需要支付任何版權費用。
???? MD5功能:
??? 輸入任意長度的信息,經過處理,輸出為128位的信息(數字指紋);
??? 不同的輸入得到的不同的結果(唯一性);
??? 根據128位的輸出結果不可能反推出輸入的信息(不可逆);?
???? MD5屬不屬于加密算法:
??? 認為不屬于的人是因為他們覺得不能從密文(散列值)反過來得到原文,即沒有解密算法,所以這部分人認為MD5只能屬于算法,不能稱為加密算法;
??? 認為屬于的人是因為他們覺得經過MD5處理后看不到原文,即已經將原文加密,所以認為MD5屬于加密算法;我個人支持后者。
???? MD5用途:
??? 1、 防止被篡改 :
??? 1)比如發送一個電子文檔,發送前,我先得到MD5的輸出結果a。然后在對方收到電子文檔后,對方也得到一個MD5的輸出結果b。如果a與b一樣就代表中途未被篡改。2)比如我提供文件下載,為了防止不法分子在安裝程序中添加木馬,我可以在網站上公布由安裝文件得到的MD5輸出結果。3)SVN在檢測文件是否在CheckOut后被修改過,也是用到了MD5.
??? 2、 防止直接看到明文 :
??? 現在很多網站在數據庫存儲用戶的密碼的時候都是存儲用戶密碼的MD5值。這樣就算不法分子得到數據庫的用戶密碼的MD5值,也無法知道用戶的密碼(其實這樣是不安全的,后面我會提到)。(比如在UNIX系統中用戶的密碼就是以MD5(或其它類似的算法)經加密后存儲在文件系統中。當用戶登錄的時候,系統把用戶輸入的密碼計算成MD5值,然后再去和保存在文件系統中的MD5值進行比較,進而確定輸入的密碼是否正確。通過這樣的步驟,系統在并不知道用戶密碼的明碼的情況下就可以確定用戶登錄系統的合法性。這不但可以避免用戶的密碼被具有系統管理員權限的用戶知道,而且還在一定程度上增加了密碼被破解的難度。)
??? 3、 防止抵賴(數字簽名):
??? 這需要一個第三方認證機構。例如A寫了一個文件,認證機構對此文件用MD5算法產生摘要信息并做好記錄。若以后A說這文件不是他寫的,權威機構只需對此文件重新產生摘要信息,然后跟記錄在冊的摘要信息進行比對,相同的話,就證明是A寫的了。這就是所謂的“數字簽名”。
??? ?MD5算法過程:
??? 對MD5算法簡要的敘述可以為:MD5以512位分組來處理輸入的信息,且每一分組又被劃分為16個32位子分組,經過了一系列的處理后,算法的輸出由四個32位分組組成,將這四個32位分組級聯后將生成一個128位散列值。
???? 第一步、填充:如果輸入信息的長度(bit)對512求余的結果不等于448,就需要填充使得對512求余的結果等于448。填充的方法是填充一個1和n個0。填充完后,信息的長度就為N*512+448(bit);
???? 第二步、記錄信息長度:用64位來存儲填充前信息長度。這64位加在第一步結果的后面,這樣信息長度就變為N*512+448+64=(N+1)*512位。
???? 第三步、裝入標準的幻數(四個整數):標準的幻數(物理順序)是(A=(01234567) 16 ,B=(89ABCDEF) 16 ,C=(FEDCBA98) 16 ,D=(76543210) 16 )。如果在程序中定義應該是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有點暈哈,其實想一想就明白了。
???? 第四步、四輪循環運算:循環的次數是分組的個數(N+1)?
???? 1)將每一512字節細分成16個小組,每個小組64位(8個字節)
?????
???? 2)先認識四個線性函數(&是與,|是或,~是非,^是異或)
??? 3)設Mj表示消息的第j個子分組(從0到15),<<<s表示循環左移s位,則四種操作為:
??? 4)四輪運算
??? 5)每輪循環后,將A,B,C,D分別加上a,b,c,d,然后進入下一循環。
?
??? 如果上面的過程用JAVA代碼來實現的話,代碼如下:?
package?woxingwosu;


/************************************************
?*?MD5?算法
?*?@author?我行我素
?*?@Date?2007-07-01
*************************************************/
public?class?MD5?{

????static?final?String?hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
????//標準的幻數
????private?static?final?long?A=0x67452301L;
????private?static?final?long?B=0xefcdab89L;
????private?static?final?long?C=0x98badcfeL;
????private?static?final?long?D=0x10325476L;

????
????//下面這些S11-S44實際上是一個4*4的矩陣,在四輪循環運算中用到
????static?final?int?S11?=?7;
????static?final?int?S12?=?12;
????static?final?int?S13?=?17;
????static?final?int?S14?=?22;

????static?final?int?S21?=?5;
????static?final?int?S22?=?9;
????static?final?int?S23?=?14;
????static?final?int?S24?=?20;

????static?final?int?S31?=?4;
????static?final?int?S32?=?11;
????static?final?int?S33?=?16;
????static?final?int?S34?=?23;

????static?final?int?S41?=?6;
????static?final?int?S42?=?10;
????static?final?int?S43?=?15;
????static?final?int?S44?=?21;
????
????//java不支持無符號的基本數據(unsigned)
????private?long?[]?result={A,B,C,D};//存儲hash結果,共4×32=128位,初始化值為(幻數的級聯)
????
????public?static?void?main(String?[]args){
????????MD5?md=new?MD5();
????????System.out.println("md5(abc)="+md.digest("abc"));
????}
????
????private?String?digest(String?inputStr){
????????byte?[]?inputBytes=inputStr.getBytes();
????????int?byteLen=inputBytes.length;//長度(字節)
????????int?groupCount=0;//完整分組的個數
????????groupCount=byteLen/64;//每組512位(64字節)
????????long?[]groups=null;//每個小組(64字節)再細分后的16個小組(4字節)
????????
????????//處理每一個完整?分組
????????for(int?step=0;step<groupCount;step++){
????????????groups=divGroup(inputBytes,step*64);
????????????trans(groups);//處理分組,核心算法
????????}
????????
????????//處理完整分組后的尾巴
????????int?rest=byteLen%64;//512位分組后的余數
????????byte?[]?tempBytes=new?byte[64];
????????if(rest<=56){
????????????for(int?i=0;i<rest;i++)
????????????????tempBytes[i]=inputBytes[byteLen-rest+i];
????????????if(rest<56){
????????????????tempBytes[rest]=(byte)(1<<7);
????????????????for(int?i=1;i<56-rest;i++)
????????????????????tempBytes[rest+i]=0;
????????????}
????????????long?len=(long)(byteLen<<3);
????????????for(int?i=0;i<8;i++){
????????????????tempBytes[56+i]=(byte)(len&0xFFL);
????????????????len=len>>8;
????????????}
????????????groups=divGroup(tempBytes,0);
????????????trans(groups);//處理分組
????????}else{
????????????for(int?i=0;i<rest;i++)
????????????????tempBytes[i]=inputBytes[byteLen-rest+i];
????????????tempBytes[rest]=(byte)(1<<7);
????????????for(int?i=rest+1;i<64;i++)
????????????????tempBytes[i]=0;
????????????groups=divGroup(tempBytes,0);
????????????trans(groups);//處理分組
????????????
????????????for(int?i=0;i<56;i++)
????????????????tempBytes[i]=0;
????????????long?len=(long)(byteLen<<3);
????????????for(int?i=0;i<8;i++){
????????????????tempBytes[56+i]=(byte)(len&0xFFL);
????????????????len=len>>8;
????????????}
????????????groups=divGroup(tempBytes,0);
????????????trans(groups);//處理分組
????????}
????????
????????//將Hash值轉換成十六進制的字符串
????????String?resStr="";
????????long?temp=0;
????????for(int?i=0;i<4;i++){
????????????for(int?j=0;j<4;j++){
????????????????temp=result[i]&0x0FL;
????????????????String?a=hexs[(int)(temp)];
????????????????result[i]=result[i]>>4;
????????????????temp=result[i]&0x0FL;
????????????????resStr+=hexs[(int)(temp)]+a;
????????????????result[i]=result[i]>>4;
????????????}
????????}
????????return?resStr;
????}
????
????/**
?????*?從inputBytes的index開始取512位,作為新的分組
?????*?將每一個512位的分組再細分成16個小組,每個小組64位(8個字節)
?????*?@param?inputBytes
?????*?@param?index
?????*?@return
?????*/
????private?static?long[]?divGroup(byte[]?inputBytes,int?index){
????????long?[]?temp=new?long[16];
????????for(int?i=0;i<16;i++){
????????????temp[i]=b2iu(inputBytes[4*i+index])|
????????????????(b2iu(inputBytes[4*i+1+index]))<<8|
????????????????(b2iu(inputBytes[4*i+2+index]))<<16|
????????????????(b2iu(inputBytes[4*i+3+index]))<<24;
????????}
????????return?temp;
????}
????
????/**
?????*?這時不存在符號位(符號位存儲不再是代表正負),所以需要處理一下
?????*?@param?b
?????*?@return
?????*/
????public?static?long?b2iu(byte?b){
????????return?b?<?0???b?&?0x7F?+?128?:?b;
?????}
????
????/**
?????*?主要的操作,四輪循環
?????*?@param?groups[]--每一個分組512位(64字節)
?????*/
????private?void?trans(long[]?groups)?{
????????long?a?=?result[0],?b?=?result[1],?c?=?result[2],?d?=?result[3];
????????/*第一輪*/
????????a?=?FF(a,?b,?c,?d,?groups[0],?S11,?0xd76aa478L);?/*?1?*/
????????d?=?FF(d,?a,?b,?c,?groups[1],?S12,?0xe8c7b756L);?/*?2?*/
????????c?=?FF(c,?d,?a,?b,?groups[2],?S13,?0x242070dbL);?/*?3?*/
????????b?=?FF(b,?c,?d,?a,?groups[3],?S14,?0xc1bdceeeL);?/*?4?*/
????????a?=?FF(a,?b,?c,?d,?groups[4],?S11,?0xf57c0fafL);?/*?5?*/
????????d?=?FF(d,?a,?b,?c,?groups[5],?S12,?0x4787c62aL);?/*?6?*/
????????c?=?FF(c,?d,?a,?b,?groups[6],?S13,?0xa8304613L);?/*?7?*/
????????b?=?FF(b,?c,?d,?a,?groups[7],?S14,?0xfd469501L);?/*?8?*/
????????a?=?FF(a,?b,?c,?d,?groups[8],?S11,?0x698098d8L);?/*?9?*/
????????d?=?FF(d,?a,?b,?c,?groups[9],?S12,?0x8b44f7afL);?/*?10?*/
????????c?=?FF(c,?d,?a,?b,?groups[10],?S13,?0xffff5bb1L);?/*?11?*/
????????b?=?FF(b,?c,?d,?a,?groups[11],?S14,?0x895cd7beL);?/*?12?*/
????????a?=?FF(a,?b,?c,?d,?groups[12],?S11,?0x6b901122L);?/*?13?*/
????????d?=?FF(d,?a,?b,?c,?groups[13],?S12,?0xfd987193L);?/*?14?*/
????????c?=?FF(c,?d,?a,?b,?groups[14],?S13,?0xa679438eL);?/*?15?*/
????????b?=?FF(b,?c,?d,?a,?groups[15],?S14,?0x49b40821L);?/*?16?*/

????????/*第二輪*/
????????a?=?GG(a,?b,?c,?d,?groups[1],?S21,?0xf61e2562L);?/*?17?*/
????????d?=?GG(d,?a,?b,?c,?groups[6],?S22,?0xc040b340L);?/*?18?*/
????????c?=?GG(c,?d,?a,?b,?groups[11],?S23,?0x265e5a51L);?/*?19?*/
????????b?=?GG(b,?c,?d,?a,?groups[0],?S24,?0xe9b6c7aaL);?/*?20?*/
????????a?=?GG(a,?b,?c,?d,?groups[5],?S21,?0xd62f105dL);?/*?21?*/
????????d?=?GG(d,?a,?b,?c,?groups[10],?S22,?0x2441453L);?/*?22?*/
????????c?=?GG(c,?d,?a,?b,?groups[15],?S23,?0xd8a1e681L);?/*?23?*/
????????b?=?GG(b,?c,?d,?a,?groups[4],?S24,?0xe7d3fbc8L);?/*?24?*/
????????a?=?GG(a,?b,?c,?d,?groups[9],?S21,?0x21e1cde6L);?/*?25?*/
????????d?=?GG(d,?a,?b,?c,?groups[14],?S22,?0xc33707d6L);?/*?26?*/
????????c?=?GG(c,?d,?a,?b,?groups[3],?S23,?0xf4d50d87L);?/*?27?*/
????????b?=?GG(b,?c,?d,?a,?groups[8],?S24,?0x455a14edL);?/*?28?*/
????????a?=?GG(a,?b,?c,?d,?groups[13],?S21,?0xa9e3e905L);?/*?29?*/
????????d?=?GG(d,?a,?b,?c,?groups[2],?S22,?0xfcefa3f8L);?/*?30?*/
????????c?=?GG(c,?d,?a,?b,?groups[7],?S23,?0x676f02d9L);?/*?31?*/
????????b?=?GG(b,?c,?d,?a,?groups[12],?S24,?0x8d2a4c8aL);?/*?32?*/

????????/*第三輪*/
????????a?=?HH(a,?b,?c,?d,?groups[5],?S31,?0xfffa3942L);?/*?33?*/
????????d?=?HH(d,?a,?b,?c,?groups[8],?S32,?0x8771f681L);?/*?34?*/
????????c?=?HH(c,?d,?a,?b,?groups[11],?S33,?0x6d9d6122L);?/*?35?*/
????????b?=?HH(b,?c,?d,?a,?groups[14],?S34,?0xfde5380cL);?/*?36?*/
????????a?=?HH(a,?b,?c,?d,?groups[1],?S31,?0xa4beea44L);?/*?37?*/
????????d?=?HH(d,?a,?b,?c,?groups[4],?S32,?0x4bdecfa9L);?/*?38?*/
????????c?=?HH(c,?d,?a,?b,?groups[7],?S33,?0xf6bb4b60L);?/*?39?*/
????????b?=?HH(b,?c,?d,?a,?groups[10],?S34,?0xbebfbc70L);?/*?40?*/
????????a?=?HH(a,?b,?c,?d,?groups[13],?S31,?0x289b7ec6L);?/*?41?*/
????????d?=?HH(d,?a,?b,?c,?groups[0],?S32,?0xeaa127faL);?/*?42?*/
????????c?=?HH(c,?d,?a,?b,?groups[3],?S33,?0xd4ef3085L);?/*?43?*/
????????b?=?HH(b,?c,?d,?a,?groups[6],?S34,?0x4881d05L);?/*?44?*/
????????a?=?HH(a,?b,?c,?d,?groups[9],?S31,?0xd9d4d039L);?/*?45?*/
????????d?=?HH(d,?a,?b,?c,?groups[12],?S32,?0xe6db99e5L);?/*?46?*/
????????c?=?HH(c,?d,?a,?b,?groups[15],?S33,?0x1fa27cf8L);?/*?47?*/
????????b?=?HH(b,?c,?d,?a,?groups[2],?S34,?0xc4ac5665L);?/*?48?*/

????????/*第四輪*/
????????a?=?II(a,?b,?c,?d,?groups[0],?S41,?0xf4292244L);?/*?49?*/
????????d?=?II(d,?a,?b,?c,?groups[7],?S42,?0x432aff97L);?/*?50?*/
????????c?=?II(c,?d,?a,?b,?groups[14],?S43,?0xab9423a7L);?/*?51?*/
????????b?=?II(b,?c,?d,?a,?groups[5],?S44,?0xfc93a039L);?/*?52?*/
????????a?=?II(a,?b,?c,?d,?groups[12],?S41,?0x655b59c3L);?/*?53?*/
????????d?=?II(d,?a,?b,?c,?groups[3],?S42,?0x8f0ccc92L);?/*?54?*/
????????c?=?II(c,?d,?a,?b,?groups[10],?S43,?0xffeff47dL);?/*?55?*/
????????b?=?II(b,?c,?d,?a,?groups[1],?S44,?0x85845dd1L);?/*?56?*/
????????a?=?II(a,?b,?c,?d,?groups[8],?S41,?0x6fa87e4fL);?/*?57?*/
????????d?=?II(d,?a,?b,?c,?groups[15],?S42,?0xfe2ce6e0L);?/*?58?*/
????????c?=?II(c,?d,?a,?b,?groups[6],?S43,?0xa3014314L);?/*?59?*/
????????b?=?II(b,?c,?d,?a,?groups[13],?S44,?0x4e0811a1L);?/*?60?*/
????????a?=?II(a,?b,?c,?d,?groups[4],?S41,?0xf7537e82L);?/*?61?*/
????????d?=?II(d,?a,?b,?c,?groups[11],?S42,?0xbd3af235L);?/*?62?*/
????????c?=?II(c,?d,?a,?b,?groups[2],?S43,?0x2ad7d2bbL);?/*?63?*/
????????b?=?II(b,?c,?d,?a,?groups[9],?S44,?0xeb86d391L);?/*?64?*/

????????/*加入到之前計算的結果當中*/
????????result[0]?+=?a;
????????result[1]?+=?b;
????????result[2]?+=?c;
????????result[3]?+=?d;
????????result[0]=result[0]&0xFFFFFFFFL;
????????result[1]=result[1]&0xFFFFFFFFL;
????????result[2]=result[2]&0xFFFFFFFFL;
????????result[3]=result[3]&0xFFFFFFFFL;
????}
????
????/**
?????*?下面是處理要用到的線性函數
?????*/
????private?static?long?F(long?x,?long?y,?long?z)?{
????????return?(x?&?y)?|?((~x)?&?z);
????}

????private?static?long?G(long?x,?long?y,?long?z)?{
????????return?(x?&?z)?|?(y?&?(~z));
????}

????private?static?long?H(long?x,?long?y,?long?z)?{
????????return?x?^?y?^?z;
????}

????private?static?long?I(long?x,?long?y,?long?z)?{
????????return?y?^?(x?|?(~z));
????}

????private?static?long?FF(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
????????????long?ac)?{
????????a?+=?(F(b,?c,?d)&0xFFFFFFFFL)?+?x?+?ac;
????????a?=?((a&0xFFFFFFFFL)<<?s)?|?((a&0xFFFFFFFFL)?>>>?(32?-?s));
????????a?+=?b;
????????return?(a&0xFFFFFFFFL);
????}

????private?static?long?GG(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
????????????long?ac)?{
????????a?+=?(G(b,?c,?d)&0xFFFFFFFFL)?+?x?+?ac;
????????a?=?((a&0xFFFFFFFFL)?<<?s)?|?((a&0xFFFFFFFFL)?>>>?(32?-?s));
????????a?+=?b;
????????return?(a&0xFFFFFFFFL);
????}

????private?static?long?HH(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
????????????long?ac)?{
????????a?+=?(H(b,?c,?d)&0xFFFFFFFFL)?+?x?+?ac;
????????a?=?((a&0xFFFFFFFFL)?<<?s)?|?((a&0xFFFFFFFFL)?>>>?(32?-?s));
????????a?+=?b;
????????return?(a&0xFFFFFFFFL);
????}

????private?static?long?II(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
????????????long?ac)?{
????????a?+=?(I(b,?c,?d)&0xFFFFFFFFL)?+?x?+?ac;
????????a?=?((a&0xFFFFFFFFL)?<<?s)?|?((a&0xFFFFFFFFL)?>>>?(32?-?s));
????????a?+=?b;
????????return?(a&0xFFFFFFFFL);
????}
}
MD5安全性:
??? 普遍認為MD5是很安全,因為暴力破解的時間是一般人無法接受的。實際上如果把用戶的密碼MD5處理后再存儲到數據庫,其實是很不安全的。因為用戶的密碼是比較短的,而且很多用戶的密碼都使用生日,手機號碼,身份證號碼,電話號碼等等。或者使用常用的一些吉利的數字,或者某個英文單詞。如果我把常用的密碼先MD5處理,把數據存儲起來,然后再跟你的MD5結果匹配,這時我就有可能得到明文。比如某個MD5破解網站 http://www.cmd5.com/default.aspx ,我把其網站下的公告復制如下
???我覺得只需要將上面我寫的MD5的標準幻數A,B,C,D的值修改一下,修改后也不是MD5算法了,因為不能保證唯一性。這樣就算別人得到32位的值,他如果不知道幻數的值是無法還原明文的。就算得到了幻數,也是很難破解的。
????? JAVA實現MD5
??? 在java中實現MD5是很簡單的,在包java.security有個類MessageDigest。官方文檔如下
package?woxingwosu;
/************************************************
?*?MD5?算法
?*?@author?我行我素
?*?@Date?2007-07-06
*************************************************/
import?java.security.MessageDigest;

public?class?MyMD5?{

????static?char[]?hex?=?{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};?
????public?static?void?main(String[]?args)?{
????????try{
????????????MessageDigest?md5?=?MessageDigest.getInstance("MD5");//申明使用MD5算法
????????????md5.update("a".getBytes());//
????????????System.out.println("md5(a)="+byte2str(md5.digest()));
????????????md5.update("a".getBytes());
????????????md5.update("bc".getBytes());
????????????System.out.println("md5(abc)="+byte2str(md5.digest()));
????????}catch(Exception?e){
????????????e.printStackTrace();
????????}
????}
????
????/**
?????*?將字節數組轉換成十六進制字符串
?????*?@param?bytes
?????*?@return
?????*/
????private?static?String?byte2str(byte?[]bytes){
????????int?len?=?bytes.length;???
????????StringBuffer?result?=?new?StringBuffer();????
????????for?(int?i?=?0;?i?<?len;?i++)?{???
????????????byte?byte0?=?bytes[i];???
????????????result.append(hex[byte0?>>>?4?&?0xf]);???
????????????result.append(hex[byte0?&?0xf]);???
????????}
????????return?result.toString();
????}
}?
??
另外附上其他版本的MD5算法的實現(
來自網絡
)
??? 1) JS版的MD5 (調用方法:md5(明文))
/*
?*?A?JavaScript?implementation?of?the?RSA?Data?Security,?Inc.?MD5?Message
?*?Digest?Algorithm,?as?defined?in?RFC?1321.
?*?Version?2.1?Copyright?(C)?Paul?Johnston?1999?-?2002.
?*?Other?contributors:?Greg?Holt,?Andrew?Kepert,?Ydnar,?Lostinet
?*?Distributed?under?the?BSD?License
?*?See?http://pajhome.org.uk/crypt/md5?for?more?info.
?*/

/*
?*?Configurable?variables.?You?may?need?to?tweak?these?to?be?compatible?with
?*?the?server-side,?but?the?defaults?work?in?most?cases.
?*/
var?hexcase?=?1;??/*?hex?output?format.?0?-?lowercase;?1?-?uppercase????????*/
var?b64pad??=?"";?/*?base-64?pad?character.?"="?for?strict?RFC?compliance???*/
var?chrsz???=?8;??/*?bits?per?input?character.?8?-?ASCII;?16?-?Unicode??????*/

/*
?*?These?are?the?functions?you'll?usually?want?to?call
?*?They?take?string?arguments?and?return?either?hex?or?base-64?encoded?strings
?*/
function?hex_md5(s){?return?binl2hex(core_md5(str2binl(s),?s.length?*?chrsz));}
function?str_md5(s){?return?binl2str(core_md5(str2binl(s),?s.length?*?chrsz));}
function?hex_hmac_md5(key,?data)?{?return?binl2hex(core_hmac_md5(key,?data));?}
function?str_hmac_md5(key,?data)?{?return?binl2str(core_hmac_md5(key,?data));?}

/*
?*?Calculate?the?MD5?of?an?array?of?little-endian?words,?and?a?bit?length
?*/
function?core_md5(x,?len)
{
??/*?append?padding?*/
??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);

}

/*
?*?These?functions?implement?the?four?basic?operations?the?algorithm?uses.
?*/
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);
}

/*
?*?Calculate?the?HMAC-MD5,?of?a?key?and?some?data
?*/
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);
}

/*
?*?Add?integers,?wrapping?at?2^32.?This?uses?16-bit?operations?internally
?*?to?work?around?bugs?in?some?JS?interpreters.
?*/
function?safe_add(x,?y)
{
??var?lsw?=?(x?&?0xFFFF)?+?(y?&?0xFFFF);
??var?msw?=?(x?>>?16)?+?(y?>>?16)?+?(lsw?>>?16);
??return?(msw?<<?16)?|?(lsw?&?0xFFFF);
}

/*
?*?Bitwise?rotate?a?32-bit?number?to?the?left.
?*/
function?bit_rol(num,?cnt)
{
??return?(num?<<?cnt)?|?(num?>>>?(32?-?cnt));
}

/*
?*?Convert?a?string?to?an?array?of?little-endian?words
?*?If?chrsz?is?ASCII,?characters?>255?have?their?hi-byte?silently?ignored.
?*/
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;
}

/*
?*?Convert?an?array?of?little-endian?words?to?a?string
?*/
function?binl2str(bin)
{
??var?str?=?"";
??var?mask?=?(1?<<?chrsz)?-?1;
??for(var?i?=?0;?i?<?bin.length?*?32;?i?+=?chrsz)
????str?+=?String.fromCharCode((bin[i>>5]?>>>?(i?%?32))?&?mask);
??return?str;
}

/*
?*?Convert?an?array?of?little-endian?words?to?a?hex?string.
?*/
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;
}

String.prototype.trim?=?function(){return?this.replace(/(^s*)|(s*$)/g,?"");}

function?md5(text)?{
????return?hex_md5(text.trim());
}
???? MD5功能:
??? 輸入任意長度的信息,經過處理,輸出為128位的信息(數字指紋);
??? 不同的輸入得到的不同的結果(唯一性);
??? 根據128位的輸出結果不可能反推出輸入的信息(不可逆);?
???? MD5屬不屬于加密算法:
??? 認為不屬于的人是因為他們覺得不能從密文(散列值)反過來得到原文,即沒有解密算法,所以這部分人認為MD5只能屬于算法,不能稱為加密算法;
??? 認為屬于的人是因為他們覺得經過MD5處理后看不到原文,即已經將原文加密,所以認為MD5屬于加密算法;我個人支持后者。
???? MD5用途:
??? 1、 防止被篡改 :
??? 1)比如發送一個電子文檔,發送前,我先得到MD5的輸出結果a。然后在對方收到電子文檔后,對方也得到一個MD5的輸出結果b。如果a與b一樣就代表中途未被篡改。2)比如我提供文件下載,為了防止不法分子在安裝程序中添加木馬,我可以在網站上公布由安裝文件得到的MD5輸出結果。3)SVN在檢測文件是否在CheckOut后被修改過,也是用到了MD5.
??? 2、 防止直接看到明文 :
??? 現在很多網站在數據庫存儲用戶的密碼的時候都是存儲用戶密碼的MD5值。這樣就算不法分子得到數據庫的用戶密碼的MD5值,也無法知道用戶的密碼(其實這樣是不安全的,后面我會提到)。(比如在UNIX系統中用戶的密碼就是以MD5(或其它類似的算法)經加密后存儲在文件系統中。當用戶登錄的時候,系統把用戶輸入的密碼計算成MD5值,然后再去和保存在文件系統中的MD5值進行比較,進而確定輸入的密碼是否正確。通過這樣的步驟,系統在并不知道用戶密碼的明碼的情況下就可以確定用戶登錄系統的合法性。這不但可以避免用戶的密碼被具有系統管理員權限的用戶知道,而且還在一定程度上增加了密碼被破解的難度。)
??? 3、 防止抵賴(數字簽名):
??? 這需要一個第三方認證機構。例如A寫了一個文件,認證機構對此文件用MD5算法產生摘要信息并做好記錄。若以后A說這文件不是他寫的,權威機構只需對此文件重新產生摘要信息,然后跟記錄在冊的摘要信息進行比對,相同的話,就證明是A寫的了。這就是所謂的“數字簽名”。
??? ?MD5算法過程:
??? 對MD5算法簡要的敘述可以為:MD5以512位分組來處理輸入的信息,且每一分組又被劃分為16個32位子分組,經過了一系列的處理后,算法的輸出由四個32位分組組成,將這四個32位分組級聯后將生成一個128位散列值。
???? 第一步、填充:如果輸入信息的長度(bit)對512求余的結果不等于448,就需要填充使得對512求余的結果等于448。填充的方法是填充一個1和n個0。填充完后,信息的長度就為N*512+448(bit);
???? 第二步、記錄信息長度:用64位來存儲填充前信息長度。這64位加在第一步結果的后面,這樣信息長度就變為N*512+448+64=(N+1)*512位。
???? 第三步、裝入標準的幻數(四個整數):標準的幻數(物理順序)是(A=(01234567) 16 ,B=(89ABCDEF) 16 ,C=(FEDCBA98) 16 ,D=(76543210) 16 )。如果在程序中定義應該是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有點暈哈,其實想一想就明白了。
???? 第四步、四輪循環運算:循環的次數是分組的個數(N+1)?
???? 1)將每一512字節細分成16個小組,每個小組64位(8個字節)
?????
???? 2)先認識四個線性函數(&是與,|是或,~是非,^是異或)
??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))
????
??G(X,Y,Z)=(X&Z)|(Y&(~Z))
??H(X,Y,Z)=X^Y^Z
??I(X,Y,Z)=Y^(X|(~Z))
??? 3)設Mj表示消息的第j個子分組(從0到15),<<<s表示循環左移s位,則四種操作為:
??FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s)
??GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s)
??HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s)
??II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)
??GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s)
??HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s)
??II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)
??? 4)四輪運算
第一輪
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)
第二輪
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三輪
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)
第四輪
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)
第二輪
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三輪
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)
第四輪
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
??? 5)每輪循環后,將A,B,C,D分別加上a,b,c,d,然后進入下一循環。
?
??? 如果上面的過程用JAVA代碼來實現的話,代碼如下:?


























































































































































































































































































??? 普遍認為MD5是很安全,因為暴力破解的時間是一般人無法接受的。實際上如果把用戶的密碼MD5處理后再存儲到數據庫,其實是很不安全的。因為用戶的密碼是比較短的,而且很多用戶的密碼都使用生日,手機號碼,身份證號碼,電話號碼等等。或者使用常用的一些吉利的數字,或者某個英文單詞。如果我把常用的密碼先MD5處理,把數據存儲起來,然后再跟你的MD5結果匹配,這時我就有可能得到明文。比如某個MD5破解網站 http://www.cmd5.com/default.aspx ,我把其網站下的公告復制如下
??md5破解、動網論壇密碼破解等不再需要用窮舉法,本站共有md5記錄235億條,還在不斷增長中,已包含10位及10位以下數字、7位字母、部分7位字母+數字,全部6位及以下字母加數字等組合,并針對國內用戶做了大量優化,例如已經包含所有手機號碼、全國部分大中城市固定電話號碼、百家姓、常用拼音等大量組合,另加入了某大型網站真實會員密碼數據10萬條。本站數據量大,查詢速度快,同時支持16位及32位密碼查詢。通過對10萬會員的真實動網論壇樣本數據的測試,本站對于動網論壇密碼的命中率達到83%。
??本站4T的硬盤已經上線,正在生成數據,預計需要2個月左右時間,到時候本站能查詢到12位數字和9位字母。
?? 你可以用你的生日,手機號碼去測試一下。
??本站4T的硬盤已經上線,正在生成數據,預計需要2個月左右時間,到時候本站能查詢到12位數字和9位字母。
???我覺得只需要將上面我寫的MD5的標準幻數A,B,C,D的值修改一下,修改后也不是MD5算法了,因為不能保證唯一性。這樣就算別人得到32位的值,他如果不知道幻數的值是無法還原明文的。就算得到了幻數,也是很難破解的。
????? JAVA實現MD5
??? 在java中實現MD5是很簡單的,在包java.security有個類MessageDigest。官方文檔如下
????MessageDigest?類為應用程序提供信息摘要算法的功能,如?MD5?或?SHA?算法。信息摘要是安全的單向哈希函數,它接收任意大小的數據,輸出固定長度的哈希值。?
????MessageDigest?對象開始被初始化。該對象通過使用?update?方法處理數據。任何時候都可以調用?reset?方法重置摘要。一旦所有需要更新的數據都已經被更新了,應該調用?digest?方法之一完成哈希計算。?
????對于給定數量的更新數據,digest?方法只能被調用一次。digest?被調用后,MessageDigest?對象被重新設置成其初始狀態。
?? 使用MessageDigest很簡單,例如?
????MessageDigest?對象開始被初始化。該對象通過使用?update?方法處理數據。任何時候都可以調用?reset?方法重置摘要。一旦所有需要更新的數據都已經被更新了,應該調用?digest?方法之一完成哈希計算。?
????對于給定數量的更新數據,digest?方法只能被調用一次。digest?被調用后,MessageDigest?對象被重新設置成其初始狀態。









































??? 1) JS版的MD5 (調用方法:md5(明文))






































































































































































































































