隨筆-153  評論-235  文章-19  trackbacks-0
          MD5
          收集于網絡


          MD5簡介:

          MD5
          的全稱是Message-Digest Algorithm 5,在90年代初由MIT的計算機科學實驗室和RSA Data Security Inc發明,經MD2MD3MD4發展而來。

          Message-Digest
          泛指字節串(Message)Hash變換,就是把一個任意長度的字節串變換成一定長的大整數。請注意我使用了字節串而不是字符串這個詞,是因為這種變換只與字節的值有關,與字符集或編碼方式無關。

          MD5
          將任意長度的字節串變換成一個128bit的大整數,并且它是一個不可逆的字符串變換算法,(我剛開始還愚蠢的認為MD5是可逆的算法感謝Stkman大哥的講解)換句話說就是,即使你看到源程序和算法描述,也無法將一個MD5的值變換回原始的字符串,從數學原理上說,是因為原始的字符串有無窮多個,這有點象不存在反函數的數學函數。

          MD5
          的典型應用是對一段Message(字節串)產生fingerprint(指紋),以防止被篡改。舉個例子,你將一段話寫在一個叫readme.txt文件中,并對這個readme.txt產生一個MD5的值并記錄在案,然后你可以傳播這個文件給別人,別人如果修改了文件中的任何內容,你對這個文件重新計算MD5時就會發現。如果再有一個第三方的認證機構,用MD5還可以防止文件作者的抵賴,這就是所謂的數字簽名應用。

          MD5
          還廣泛用于加密和解密技術上,在很多操作系統中,用戶的密碼是以MD5值(或類似的其它算法)的方式保存的,用戶Login的時候,系統是把用戶輸入的密碼計算成MD5值,然后再去和系統中保存的MD5值進行比較,而系統并不知道用戶的密碼是什么。

          一些黑客破獲這種密碼的方法是一種被稱為跑字典的方法。有兩種方法得到字典,一種是日常搜集的用做密碼的字符串表,另一種是用排列組合方法生成的,先用MD5程序計算出這些字典項的MD5值,然后再用目標的MD5值在這個字典中檢索。

          即使假設密碼的最大長度為8,同時密碼只能是字母和數字,共26+26+10=62個字符,排列組合出的字典的項數則是P(62,1)+P(62,2)….+P(62,8),那也已經是一個很天文的數字了,存儲這個字典就需要TB級的磁盤組,而且這種方法還有一個前提,就是能獲得目標賬戶的密碼MD5值的情況下才可以。

          在軟件的加密保護中 很多軟件采用MD5保護 但是由于MD5算法為不可逆算法所以所有的軟件都是使用MD5算法作為一個加密的中間步驟,比如對用戶名做一個MD5變換,結果再進行一個可逆的加密變換,做注冊機時也只要先用MD5變換,然后再用一個逆算法。所以對于破解者來說只要能看出是MD5就很容易了。

          MD5
          代碼的特點明顯,跟蹤時很容易發現,如果軟件采用MD5算法,在數據初始化的時候必然用到以下的四個常數
          0x67452301;
          0xefcdab89;
          0x98badcfe;
          0x10325476;
          若常數不等 則可能是變形的MD5算法 或者根本就不是這個算法。在內存了也就是
          01 23 45 67 89 ab cd ef fe dc ......32 10 16
          個字節
          ————————————————————————————————————————————

          MD5
          算法:

          第一步:增加填充
          增加padding使得數據長度(bit為單位)模512448。如果數據長度正好是模512448,增加512個填充bit,也就是說填充的個數為1-512。第一個bit1,其余全部為0
          第二步:補足長度
          將數據長度轉換為64bit的數值,如果長度超過64bit所能表示的數據長度的范圍,值保留最后64bit,增加到前面填充的數據后面,使得最后的數據為512bit的整數倍。也就是32bit16倍的整數倍。在RFC1321中,32bit稱為一個word
          第三步:初始化變量:
          用到4個變量,分別為ABCD,均為32bit長。初始化為:
          A: 01 23 45 67
          B: 89 ab cd ef
          C: fe dc ba 98
          D: 76 54 32 10
          第四步:數據處理:
          首先定義4個輔助函數:
          F(X,Y,Z) = XY v not(X) Z
          G(X,Y,Z) = XZ v Y not(Z)
          H(X,Y,Z) = X xor Y xor Z
          I(X,Y,Z) = Y xor (X v not(Z))
          其中:XY表示按位與,X v Y表示按位或,not(X)表示按位取反。xor表示按位異或。
          函數中的XYZ均為32bit

          定義一個需要用到的數組:T(i),i取值1-64,T(i)等于abs(sin(i))4294967296倍的整數部分,i為弧度。
          假設前三步處理后的數據長度為32*16*Nbit

          第五步:輸出:
          最后得到的ABCD為輸出結果,共128bitA為低位,D為高位。


          MD5在編程中的實現--JAVA



          /************************************************
          MD5?算法的Java?Bean
          ************************************************
          */
          import?java.lang.reflect.*;
          /*************************************************
          md5?類實現了RSA?Data?Security,?Inc.在提交給IETF
          的RFC1321中的MD5?message-digest?算法。
          ************************************************
          */

          public?class?MD5?{
          ????
          /*?下面這些S11-S44實際上是一個4*4的矩陣,在原始的C實現中是用#define?實現的,
          ????這里把它們實現成為static?final是表示了只讀,切能在同一個進程空間內的多個
          ????Instance間共享
          */
          ????????
          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;

          ????????
          static?final?byte[]?PADDING?=?{?-128,?0,?0,?0,?0,?0,?0,?0,?0,
          ????????
          0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,
          ????????
          0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,
          ????????
          0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0,?0?};
          ????????
          /*?下面的三個成員是MD5計算過程中用到的3個核心數據,在原始的C實現中
          ???????????被定義到MD5_CTX結構中

          ?????????
          */
          ????????
          private?long[]?state?=?new?long[4];??//?state?(ABCD)
          ????????private?long[]?count?=?new?long[2];??//?number?of?bits,?modulo?2^64?(lsb?first)
          ????????private?byte[]?buffer?=?new?byte[64];?//?input?buffer

          ????
          /*?digestHexStr是MD5的唯一一個公共成員,是最新一次計算結果的
          ???? ?16進制ASCII表示.
          ????
          */
          ????????
          public?String?digestHexStr;

          ????????
          /*?digest,是最新一次計算結果的2進制內部表示,表示128bit的MD5值.
          ????
          */
          ????????
          private?byte[]?digest?=?new?byte[16];

          ????
          /*
          ??????getMD5ofStr是類MD5最主要的公共方法,入口參數是你想要進行MD5變換的字符串
          ??????返回的是變換完的結果,這個結果是從公共成員digestHexStr取得的.
          ????
          */
          ????????
          public?String?getMD5ofStr(String?inbuf)?{
          ????????????????md5Init();
          ????????????????md5Update(inbuf.getBytes(),?inbuf.length());
          ????????????????md5Final();
          ????????????????digestHexStr?
          =?"";
          ????????????????
          for?(int?i?=?0;?i?<?16;?i++)?{
          ????????????????????????digestHexStr?
          +=?byteHEX(digest[i]);
          ????????????????}
          ????????????????
          return?digestHexStr;

          ????????}
          ????????
          //?這是MD5這個類的標準構造函數,JavaBean要求有一個public的并且沒有參數的構造函數
          ????????public?MD5()?{
          ????????????????md5Init();

          ????????????????
          return;
          ????????}

          ?

          ????????
          /*?md5Init是一個初始化函數,初始化核心變量,裝入標準的幻數?*/
          ????????
          private?void?md5Init()?{
          ????????????????count[
          0]?=?0L;
          ????????????????count[
          1]?=?0L;
          ????????????????
          ///*?Load?magic?initialization?constants.

          ????????????????state[
          0]?=?0x67452301L;
          ????????????????state[
          1]?=?0xefcdab89L;
          ????????????????state[
          2]?=?0x98badcfeL;
          ????????????????state[
          3]?=?0x10325476L;

          ????????????????
          return;
          ????????}
          ????????
          /*?F,?G,?H?,I?是4個基本的MD5函數,在原始的MD5的C實現中,由于它們是
          ????????簡單的位運算,可能出于效率的考慮把它們實現成了宏,在java中,我們把它們
          ?????  實現成了private方法,名字保持了原來C中的。?
          */

          ????????
          private?long?F(long?x,?long?y,?long?z)?{
          ????????????????
          return?(x?&?y)?|?((~x)?&?z);

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

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

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

          ???????
          /*
          ??????????FF,GG,HH和II將調用F,G,H,I進行近一步變換
          ??????????FF,?GG,?HH,?and?II?transformations?for?rounds?1,?2,?3,?and?4.
          ??????????Rotation?is?separate?from?addition?to?prevent?recomputation.
          ???????
          */

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

          ????????
          private?long?GG(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
          ????????????????
          long?ac)?{
          ????????????????a?
          +=?G?(b,?c,?d)?+?x?+?ac;
          ????????????????a?
          =?((int)?a?<<?s)?|?((int)?a?>>>?(32?-?s));
          ????????????????a?
          +=?b;
          ????????????????
          return?a;
          ????????}
          ????????
          private?long?HH(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
          ????????????????
          long?ac)?{
          ????????????????a?
          +=?H?(b,?c,?d)?+?x?+?ac;
          ????????????????a?
          =?((int)?a?<<?s)?|?((int)?a?>>>?(32?-?s));
          ????????????????a?
          +=?b;
          ????????????????
          return?a;
          ????????}
          ????????
          private?long?II(long?a,?long?b,?long?c,?long?d,?long?x,?long?s,
          ????????????????
          long?ac)?{
          ????????????????a?
          +=?I?(b,?c,?d)?+?x?+?ac;
          ????????????????a?
          =?((int)?a?<<?s)?|?((int)?a?>>>?(32?-?s));
          ????????????????a?
          +=?b;
          ????????????????
          return?a;
          ????????}
          ????????
          /*
          ?????????md5Update是MD5的主計算過程,inbuf是要變換的字節串,inputlen是長度,這個
          ?????????函數由getMD5ofStr調用,調用之前需要調用md5init,因此把它設計成private的
          ????????
          */
          ????????
          private?void?md5Update(byte[]?inbuf,?int?inputLen)?{

          ????????????????
          int?i,?index,?partLen;
          ????????????????
          byte[]?block?=?new?byte[64];
          ????????????????index?
          =?(int)(count[0]?>>>?3)?&?0x3F;
          ????????????????
          //?/*?Update?number?of?bits?*/
          ????????????????if?((count[0]?+=?(inputLen?<<?3))?<?(inputLen?<<?3))
          ????????????????????????count[
          1]++;
          ????????????????count[
          1]?+=?(inputLen?>>>?29);

          ????????????????partLen?
          =?64?-?index;

          ????????????????
          //?Transform?as?many?times?as?possible.
          ????????????????if?(inputLen?>=?partLen)?{
          ????????????????????????md5Memcpy(buffer,?inbuf,?index,?
          0,?partLen);
          ????????????????????????md5Transform(buffer);

          ????????????????????????
          for?(i?=?partLen;?i?+?63?<?inputLen;?i?+=?64)?{

          ????????????????????????????????md5Memcpy(block,?inbuf,?
          0,?i,?64);
          ????????????????????????????????md5Transform?(block);
          ????????????????????????}
          ????????????????????????index?
          =?0;

          ????????????????}?
          else

          ????????????????????????i?
          =?0;

          ????????????????
          ///*?Buffer?remaining?input?*/
          ????????????????md5Memcpy(buffer,?inbuf,?index,?i,?inputLen?-?i);

          ????????}

          ????????
          /*
          ??????????md5Final整理和填寫輸出結果
          ????????
          */
          ????????
          private?void?md5Final?()?{
          ????????????????
          byte[]?bits?=?new?byte[8];
          ????????????????
          int?index,?padLen;

          ????????????????
          ///*?Save?number?of?bits?*/
          ????????????????Encode?(bits,?count,?8);

          ????????????????
          ///*?Pad?out?to?56?mod?64.
          ????????????????index?=?(int)(count[0]?>>>?3)?&?0x3f;
          ????????????????padLen?
          =?(index?<?56)???(56?-?index)?:?(120?-?index);
          ????????????????md5Update?(PADDING,?padLen);

          ????????????????
          ///*?Append?length?(before?padding)?*/
          ????????????????md5Update(bits,?8);

          ????????????????
          ///*?Store?state?in?digest?*/
          ????????????????Encode?(digest,?state,?16);

          ????????}

          ????????
          /*?md5Memcpy是一個內部使用的byte數組的塊拷貝函數,從input的inpos開始把len長度的
               ?字節拷貝到output的outpos位置開始
          ????????
          */

          ????????
          private?void?md5Memcpy?(byte[]?output,?byte[]?input,
          ????????????????
          int?outpos,?int?inpos,?int?len)
          ????????{
          ????????????????
          int?i;

          ????????????????
          for?(i?=?0;?i?<?len;?i++)
          ????????????????????????output[outpos?
          +?i]?=?input[inpos?+?i];
          ????????}

          ????????
          /*
          ???????????md5Transform是MD5核心變換程序,有md5Update調用,block是分塊的原始字節
          ????????
          */
          ????????
          private?void?md5Transform?(byte?block[])?{
          ????????????????
          long?a?=?state[0],?b?=?state[1],?c?=?state[2],?d?=?state[3];
          ????????????????
          long[]?x?=?new?long[16];

          ????????????????Decode?(x,?block,?
          64);

          ????????????????
          /*?Round?1?*/
          ????????????????a?
          =?FF?(a,?b,?c,?d,?x[0],?S11,?0xd76aa478L);?/*?1?*/
          ????????????????d?
          =?FF?(d,?a,?b,?c,?x[1],?S12,?0xe8c7b756L);?/*?2?*/
          ????????????????c?
          =?FF?(c,?d,?a,?b,?x[2],?S13,?0x242070dbL);?/*?3?*/
          ????????????????b?
          =?FF?(b,?c,?d,?a,?x[3],?S14,?0xc1bdceeeL);?/*?4?*/
          ????????????????a?
          =?FF?(a,?b,?c,?d,?x[4],?S11,?0xf57c0fafL);?/*?5?*/
          ????????????????d?
          =?FF?(d,?a,?b,?c,?x[5],?S12,?0x4787c62aL);?/*?6?*/
          ????????????????c?
          =?FF?(c,?d,?a,?b,?x[6],?S13,?0xa8304613L);?/*?7?*/
          ????????????????b?
          =?FF?(b,?c,?d,?a,?x[7],?S14,?0xfd469501L);?/*?8?*/
          ????????????????a?
          =?FF?(a,?b,?c,?d,?x[8],?S11,?0x698098d8L);?/*?9?*/
          ????????????????d?
          =?FF?(d,?a,?b,?c,?x[9],?S12,?0x8b44f7afL);?/*?10?*/
          ????????????????c?
          =?FF?(c,?d,?a,?b,?x[10],?S13,?0xffff5bb1L);?/*?11?*/
          ????????????????b?
          =?FF?(b,?c,?d,?a,?x[11],?S14,?0x895cd7beL);?/*?12?*/
          ????????????????a?
          =?FF?(a,?b,?c,?d,?x[12],?S11,?0x6b901122L);?/*?13?*/
          ????????????????d?
          =?FF?(d,?a,?b,?c,?x[13],?S12,?0xfd987193L);?/*?14?*/
          ????????????????c?
          =?FF?(c,?d,?a,?b,?x[14],?S13,?0xa679438eL);?/*?15?*/
          ????????????????b?
          =?FF?(b,?c,?d,?a,?x[15],?S14,?0x49b40821L);?/*?16?*/

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

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

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

          ????????????????state[
          0]?+=?a;
          ????????????????state[
          1]?+=?b;
          ????????????????state[
          2]?+=?c;
          ????????????????state[
          3]?+=?d;

          ????????}

          ????????
          /*Encode把long數組按順序拆成byte數組,因為java的long類型是64bit的,
          ??????????只拆低32bit,以適應原始C實現的用途
          ????????
          */
          ????????
          private?void?Encode?(byte[]?output,?long[]?input,?int?len)?{
          ????????????????
          int?i,?j;

          ????????????????
          for?(i?=?0,?j?=?0;?j?<?len;?i++,?j?+=?4)?{
          ????????????????????????output[j]?
          =?(byte)(input[i]?&?0xffL);
          ????????????????????????output[j?
          +?1]?=?(byte)((input[i]?>>>?8)?&?0xffL);
          ????????????????????????output[j?
          +?2]?=?(byte)((input[i]?>>>?16)?&?0xffL);
          ????????????????????????output[j?
          +?3]?=?(byte)((input[i]?>>>?24)?&?0xffL);
          ????????????????}
          ????????}

          ????????
          /*Decode把byte數組按順序合成成long數組,因為java的long類型是64bit的,
          ??????????只合成低32bit,高32bit清零,以適應原始C實現的用途
          ????????
          */
          ????????
          private?void?Decode?(long[]?output,?byte[]?input,?int?len)?{
          ????????????????
          int?i,?j;


          ????????????????
          for?(i?=?0,?j?=?0;?j?<?len;?i++,?j?+=?4)
          ????????????????????????output[i]?
          =?b2iu(input[j])?|
          ????????????????????????????????(b2iu(input[j?
          +?1])?<<?8)?|
          ????????????????????????????????(b2iu(input[j?
          +?2])?<<?16)?|
          ????????????????????????????????(b2iu(input[j?
          +?3])?<<?24);

          ????????????????
          return;
          ????????}

          ????????
          /*
          ??????????b2iu是我寫的一個把byte按照不考慮正負號的原則的"升位"程序,因為java沒有unsigned運算
          ????????
          */
          ????????
          public?static?long?b2iu(byte?b)?{
          ????????????????
          return?b?<?0???b?&?0x7F?+?128?:?b;
          ????????}

          ????
          /*byteHEX(),用來把一個byte類型的數轉換成十六進制的ASCII表示,
          ???? 因為java中的byte的toString無法實現這一點,我們又沒有C語言中的
          ??????sprintf(outbuf,"%02X",ib)
          ????
          */
          ????????
          public?static?String?byteHEX(byte?ib)?{
          ????????????????
          char[]?Digit?=?{?'0','1','2','3','4','5','6','7','8','9',
          ????????????????
          'A','B','C','D','E','F'?};
          ????????????????
          char?[]?ob?=?new?char[2];
          ????????????????ob[
          0]?=?Digit[(ib?>>>?4)?&?0X0F];
          ????????????????ob[
          1]?=?Digit[ib?&?0X0F];
          ????????????????String?s?
          =?new?String(ob);
          ????????????????
          return?s;
          ????????}

          ????????
          public?static?void?main(String?args[])?{


          ????????????????MD5?m?
          =?new?MD5();
          ????????????????
          if?(Array.getLength(args)?==?0)?{???//如果沒有參數,執行標準的Test?Suite

          ???????????????????????????System.out.println(
          "MD5?Test?suite:");
          ????????????????????System.out.println(
          "MD5(\"\"):"+m.getMD5ofStr(""));
          ????????????????????System.out.println(
          "MD5(\"a\"):"+m.getMD5ofStr("a"));
          ????????????????????System.out.println(
          "MD5(\"abc\"):"+m.getMD5ofStr("abc"));
          ????????????????????System.out.println(
          "MD5(\"message?digest\"):"+m.getMD5ofStr("message?digest"));
          ????????????????????System.out.println(
          "MD5(\"abcdefghijklmnopqrstuvwxyz\"):"+
          ????????????????????????m.getMD5ofStr(
          "abcdefghijklmnopqrstuvwxyz"));
          ????????????????????System.out.println(
          "MD5(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"):"+
          ?????????????????????????m.getMD5ofStr(
          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"));
          ????????????????????
          ????????????????????
          ????????????????}
          ????????????????
          else
          ??????????????????????????System.out.println(
          "MD5("?+?args[0]?+?")="?+?m.getMD5ofStr(args[0]));


          ????????????????String?a
          =m.getMD5ofStr(new?String("jkz"));
          ????????????????System.out.print(a
          +"?"+a.equals(m.getMD5ofStr(new?String("aaaa"))));
          ????????}

          }

          posted on 2006-11-24 21:12 流浪汗 閱讀(945) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 三穗县| 乳山市| 屏东县| 华坪县| 康定县| 海城市| 双流县| 高碑店市| 论坛| 彰武县| 平阴县| 浦北县| 乌鲁木齐县| 井冈山市| 巴塘县| 华蓥市| 双柏县| 绿春县| 台东市| 青海省| 思茅市| 成都市| 社旗县| 故城县| 左贡县| 金门县| 张家口市| 邢台市| 龙里县| 高青县| 卓尼县| 信宜市| 鄂伦春自治旗| 普定县| 普兰店市| 拉萨市| 禄劝| 宜春市| 会东县| 固原市| 庄浪县|