( f' O- {- _% S+ o) p 删去了一些无用的#if define,因为我只关心MD5,这个推荐的C实现同时实现了MD2 MD3和 MD4,而且有些#if define还和C不同编译器有关 9 I3 G/ K3 s) o( E
5 x; V$ _' ?" q; ^5 c
将一些计算宏转换成final static 成员函数。 ) G) r& T$ r0 A+ H' v3 S D" E; P
# {2 q3 [4 K& W7 X 所有的变量命名与原来C实现中保持一致,在大小写上作一些符合Java习惯的变化,计算过程中的C函数变成了private方法(成员函数)。 # k/ E- A9 s% M
7 l) s0 {4 z/ m 关键变量的位长调整 ]0 v# c$ j0 I; z/ `5 s1 w4 E
9 J. Y. P5 n) Z6 I
定义了类和方法 ( z) f: s/ \! [% {) ]2 I 2 }5 y6 [/ U( H 需要注意的是,很多早期的C编译器的int类型是16 bit的,MD5使用了unsigned long int,并认为它是32bit的无符号整数。而在Java中int是32 bit的,long是64 bit的。在MD5的C实现中,使用了大量的位操作。这里需要指出的一点是,尽管Java提供了位操作,由于Java没有unsigned类型,对于右移位操作多提供了一个无符号右移:>>>,等价于C中的 >> 对于unsigned 数的处理。 ; r) h( F1 u5 m, o; P5 Z Q/ f S- ?" I3 C+ h6 M5 s 因为Java不提供无符号数的运算,两个大int数相加就会溢出得到一个负数或异常,因此我将一些关键变量在Java中改成了long类型(64bit)。我个人认为这比自己去重新定义一组无符号数的类同时重载那些运算符要方便,同时效率高很多并且代码也易读,OO(Object Oriented)的滥用反而会导致效率低下。 0 `' o' H. F) \/ C
5 z4 | d" c7 r Q% ?8 _ 限于篇幅,这里不再给出原始的C代码,有兴趣对照的读者朋友可以去看RFC 1321。MD5.java源代码 & H {0 I! U, }! ?+ k! q& k4 A' U6 {, T
测试 ) F, O, ^9 T. z4 s. n$ ?# m7 o! M7 ?8 |' w V' ?
在RFC 1321中,给出了Test suite用来检验你的实现是否正确: / C: G. M' G' c, M4 i5 T; s
& U- j% d! z, U- p5 b+ GMD5 ("") = d41d8cd98f00b204e9800998ecf8427e / p4 P4 Q8 v, @6 m! x Z1 s O4 w4 ~ # I6 }( ^6 _. ~2 p [0 ]MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 + l% B! [/ b9 g8 a ^; H+ `$ {+ A9 G5 m$ j z' _# ^
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 + E) m, ^; c. d/ O8 n6 W