/**
* @(#)MD5.java
*
*
* @SuLyin
* @version 1.00 2008/10/6
*/
package com.sulyin.ustbphone;
public class MD5
{
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 };
/* 计算过程中的三个核心数据 */
private long[] state = new long[ 4 ];
private long[] count = new long[ 2 ];
private byte[] buffer = new byte[ 64 ];
/* 最新一次计算结果的16进制ASCII表示(公共成员-digestHexStr)*/
public String digestHexStr;
/* 最新一次计算结果的二进制内部表示,表示128位的MD5值(私有成员-digest)*/
private byte[] digest = new byte[ 16 ];
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;
}
public MD5()
{
md5Init();
return;
}
private void md5Init()
{
count[ 0 ] = 0L;
count[ 1 ] = 0L;
state[ 0 ] = 0x67452301L;
state[ 1 ] = 0xefcdab89L;
state[ 2 ] = 0x98badcfeL;
state[ 3 ] = 0x10325476L;
return;
}
/* F,G,H,I四个基本的MD5函数,实现简单的位运算。*/
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进行进一步变换 */
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;
if( ( count[ 0 ] += ( inputLen << 3 ) ) < ( inputLen << 3 ) )
count[ 1 ] ++;
count[ 1 ] += ( inputLen >>> 29 );
partLen = 64 - index;
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;
md5Memcpy( buffer, inbuf, index, i, inputLen - i );
}
/* md5Final整理和填写输出结果 */
private void md5Final()
{
byte[] bits = new byte[ 8 ];
int index, padLen;
Encode( bits, count, 8 );
index = ( int )( count[ 0 ] >>> 3 ) & 0x3f;
padLen = ( index < 56 ) ? ( 56 - index ) : ( 120 - index );
md5Update( PADDING, padLen );
md5Update( bits, 8 );
Encode( digest, state, 16 );
}
/* md5Memcopy是一个内部使用的byte数组的块复制函数,从input的inpos开始把len长度的字节复制到ouput的outpos位置开始 */
private void md5Memcpy( byte[] output, byte[] input, int outpos, int inpos, int len )
{
int i;
for( i = 0; i < len; i ++ )
{
output[ outpos + 1 ] = input[ inpos + 1 ];
}
}
/* 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类型是64位的,所以只拆低32位,以适应原始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类型是64位的,因此只合成低32位,高32位清零 */
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 );
}
}
/* b2iu是一个附加的把byte按照不考虑正负号的原则的“升位”函数,因为java没有unsigned运算 */
public static long b2iu( byte b )
{
return b < 0 ? b & 0x7F + 128 : b;
}
/* byteHEX()用来把一个byte类型的数转换成十六进制的ASCII表示,因为toString方法无法做到这一点 */
public static String byteHEX( byte ib )
{
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', '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 String toMD5( String source )
{
MD5 md5 = new MD5();
return md5.getMD5ofStr( source );
}
}