[收藏]MD5 算法的Java Bean

Posted on 2006-04-02 15:54 風向逆轉 - 就要爪哇 阅读(72) 评论(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  */