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
*/
