[收藏]MD5 算法的Java Bean

Posted on 2006-04-02 15:54 ikingqu 阅读(230) 评论(0)  编辑  收藏 所属分类: JavaSE&JavaEE
  /** **********************************************
 MD5 算法的Java Bean
 
@author :Topcat Tuppin
 Last Modified:10,Mar,2001
 ************************************************
*/

package  org.waityou.news.util;

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(\ " 850817 \ " ): "   +  m.getMD5ofStr( " 850817 " ));
            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 ]));

    }


}

只有注册用户登录后才能发表评论。


网站导航:
 

posts - 4, comments - 5, trackbacks - 0, articles - 60

Copyright © ikingqu