/**/ /*
* 创建日期 2006-10-8
*
* TODO 要更改此生成的文件的模板,请转至
* 窗口 - 首选项 - Java - 代码样式 - 代码模板
*/
package com.yzp;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util. * ;
public class MD5 ... {
private int a = 0x67452301;
private int b = 0xefcdab89;
private int c = 0x98badcfe;
private int d = 0x10325476;
public int[] GetByte(String msg)
...{
byte[] bs;
try
...{
bs = msg.getBytes("ASCII");
}
catch (Exception e)
...{
bs = msg.getBytes();
}
int oldLn = bs.length*8;
int totalLn = bs.length+(64-((bs.length+8)%64))+8;
byte[] newbs = new byte[totalLn];
int i=0;
for (i=0;i<bs.length;i++)
newbs[i]=bs[i];
if (totalLn!=bs.length)
newbs[i++]=(byte)0x80;
for (;i<totalLn;i++)
newbs[i]=0;
for (i=0;i<4;i++)
...{
newbs[totalLn-8+i]=(byte)(oldLn>>(8*i)&0xFF);
}
int[] result=new int[totalLn/4];
for (i=0;i<result.length;i++)
...{
int h1=newbs[i*4]&0x0000FFFF;
int h2=newbs[i*4+1]<<8&0x0000FFFF;
int h3=newbs[i*4+2]<<16&0x0000FFFF;
int h4=newbs[i*4+3]<<24&0x0000FFFF;
//result[i] = newbs[i*4]|newbs[i*4+1]<<8|newbs[i*4+2]<<16|newbs[i*4+3]<<24;
result[i] = h1|h2|h3|h4;
}
return result;
}
private int F(int x,int y,int z)
...{
return (x&y)|((~x)&z);
}
private int G(int x,int y,int z)
...{
return (x&z)|(y&(~z));
}
private int H(int x,int y,int z)
...{
return x^y^z;
}
private int I(int x,int y,int z)
...{
return y^(x|(~z));
}
private int FF(int a,int b,int c,int d,int mj,int s,int ti)
...{
a = a+F(b,c,d)+mj+ti;
a = (a << s) | (a >>> (32-s));
a += b;
return a;
}
private int GG(int a,int b,int c,int d,int mj,int s,int ti)
...{
a = a+G(b,c,d)+mj+ti;
a = a << s | a >>> (32-s);
a += b;
return a;
}
private int HH(int a,int b,int c,int d,int mj,int s,int ti)
...{
a = a+H(b,c,d)+mj+ti;
a = a << s | a >>> (32-s);
a += b;
return a;
}
private int II(int a,int b,int c,int d,int mj,int s,int ti)
...{
a = a+I(b,c,d)+mj+ti;
a = a << s | a >>> (32-s);
a += b;
return a;
}
private final int s11 = 7;
private final int s12 = 12;
private final int s13 = 17;
private final int s14 = 22;
private final int s21 = 5;
private final int s22 = 9;
private final int s23 = 14;
private final int s24 = 20;
private final int s31 = 4;
private final int s32 = 11;
private final int s33 = 16;
private final int s34 = 23;
private final int s41 = 6;
private final int s42 = 10;
private final int s43 = 15;
private final int s44 = 21;
public String toMD5(int[] x)
...{
a = 0x67452301;
b = 0xefcdab89;
c = 0x98badcfe;
d = 0x10325476;
int la,lb,lc,ld;
for (int k=0;k<x.length/16;k+=16)
...{
la=a;lb=b;lc=c;ld=d;
//Round 1
la = FF(la,lb,lc,ld,x[k+ 0],s11,0xd76aa478);
ld = FF(ld,la,lb,lc,x[k+ 1],s12,0xe8c7b756);
lc = FF(lc,ld,la,lb,x[k+ 2],s13,0x242070db);
lb = FF(lb,lc,ld,la,x[k+ 3],s14,0xc1bdceee);
la = FF(la,lb,lc,ld,x[k+ 4],s11,0xf57c0faf);
ld = FF(ld,la,lb,lc,x[k+ 5],s12,0x4787c62a);
lc = FF(lc,ld,la,lb,x[k+ 6],s13,0xa8304613);
lb = FF(lb,lc,ld,la,x[k+ 7],s14,0xfd469501);
la = FF(la,lb,lc,ld,x[k+ 8],s11,0x698098d8);
ld = FF(ld,la,lb,lc,x[k+ 9],s12,0x8b44f7af);
lc = FF(lc,ld,la,lb,x[k+10],s13,0xffff5bb1);
lb = FF(lb,lc,ld,la,x[k+11],s14,0x895cd7be);
la = FF(la,lb,lc,ld,x[k+12],s11,0x6b901122);
ld = FF(ld,la,lb,lc,x[k+13],s12,0xfd987193);
lc = FF(lc,ld,la,lb,x[k+14],s13,0xa679438e);
lb = FF(lb,lc,ld,la,x[k+15],s14,0x49b40821);
//Round2
la = GG(la,lb,lc,ld,x[k+ 1],s21,0xf61e2562);
ld = GG(ld,la,lb,lc,x[k+ 6],s22,0xc040b340);
lc = GG(lc,ld,la,lb,x[k+11],s23,0x265e5a51);
lb = GG(lb,lc,ld,la,x[k+ 0],s24,0xe9b6c7aa);
la = GG(la,lb,lc,ld,x[k+ 5],s21,0xd62f105d);
ld = GG(ld,la,lb,lc,x[k+10],s22,0x2441453);
lc = GG(lc,ld,la,lb,x[k+15],s23,0xd8a1e681);
lb = GG(lb,lc,ld,la,x[k+ 4],s24,0xe7d3fbc8);
la = GG(la,lb,lc,ld,x[k+ 9],s21,0x21e1cde6);
ld = GG(ld,la,lb,lc,x[k+14],s22,0xc33707d6);
lc = GG(lc,ld,la,lb,x[k+ 3],s23,0xf4d50d87);
lb = GG(lb,lc,ld,la,x[k+ 8],s24,0x455a14ed);
la = GG(la,lb,lc,ld,x[k+13],s21,0xa9e3e905);
ld = GG(ld,la,lb,lc,x[k+ 2],s22,0xfcefa3f8);
lc = GG(lc,ld,la,lb,x[k+ 7],s23,0x676f02d9);
lb = GG(lb,lc,ld,la,x[k+12],s24,0x8d2a4c8a);
//Round 3
la = HH(la,lb,lc,ld,x[k+ 5],s31,0xfffa3942);
ld = HH(ld,la,lb,lc,x[k+ 8],s32,0x8771f681);
lc = HH(lc,ld,la,lb,x[k+11],s33,0x6d9d6122);
lb = HH(lb,lc,ld,la,x[k+14],s34,0xfde5380c);
la = HH(la,lb,lc,ld,x[k+ 1],s31,0xa4beea44);
ld = HH(ld,la,lb,lc,x[k+ 4],s32,0x4bdecfa9);
lc = HH(lc,ld,la,lb,x[k+ 7],s33,0xf6bb4b60);
lb = HH(lb,lc,ld,la,x[k+10],s34,0xbebfbc70);
la = HH(la,lb,lc,ld,x[k+13],s31,0x289b7ec6);
ld = HH(ld,la,lb,lc,x[k+ 0],s32,0xeaa127fa);
lc = HH(lc,ld,la,lb,x[k+ 3],s33,0xd4ef3085);
lb = HH(lb,lc,ld,la,x[k+ 6],s34,0x4881d05);
la = HH(la,lb,lc,ld,x[k+ 9],s31,0xd9d4d039);
ld = HH(ld,la,lb,lc,x[k+12],s32,0xe6db99e5);
lc = HH(lc,ld,la,lb,x[k+15],s33,0x1fa27cf8);
lb = HH(lb,lc,ld,la,x[k+ 2],s34,0xc4ac5665);
//Round4
la = II(la,lb,lc,ld,x[k+ 0],s41,0xf4292244);
ld = II(ld,la,lb,lc,x[k+ 7],s42,0x432aff97);
lc = II(lc,ld,la,lb,x[k+14],s43,0xab9423a7);
lb = II(lb,lc,ld,la,x[k+ 5],s44,0xfc93a039);
la = II(la,lb,lc,ld,x[k+12],s41,0x655b59c3);
ld = II(ld,la,lb,lc,x[k+ 3],s42,0x8f0ccc92);
lc = II(lc,ld,la,lb,x[k+10],s43,0xffeff47d);
lb = II(lb,lc,ld,la,x[k+ 1],s44,0x85845dd1);
la = II(la,lb,lc,ld,x[k+ 8],s41,0x6fa87e4f);
ld = II(ld,la,lb,lc,x[k+15],s42,0xfe2ce6e0);
lc = II(lc,ld,la,lb,x[k+ 6],s43,0xa3014314);
lb = II(lb,lc,ld,la,x[k+13],s44,0x4e0811a1);
la = II(la,lb,lc,ld,x[k+ 4],s41,0xf7537e82);
ld = II(ld,la,lb,lc,x[k+11],s42,0xbd3af235);
lc = II(lc,ld,la,lb,x[k+ 2],s43,0x2ad7d2bb);
lb = II(lb,lc,ld,la,x[k+ 9],s44,0xeb86d391);
a+=la;
b+=lb;
c+=lc;
d+=ld;
}
int[] lr = new int[]...{a,b,c,d};
String r = "";
for (int i=0;i<lr.length;i++)...{
for (int j=0;j<4;j++)...{
r+=" "+Integer.toHexString((int)((lr[i]>>>(j*8))&0xFF));
}
}
return r;
}
public static void main(String[] arg) throws ClassNotFoundException
...{
MD5 m = new MD5();
System.out.println(m.toMD5(m.GetByte("a")));
}
}
终于决心学一下java了,初步看了一下书,感觉它也并不像想像中的那么强大,在语言特性上我甚至觉得它还不如 C#。今天就试着用它来实现了一个MD5的算法。使用起来感觉很不习惯。
在语言特性上与C#有以下差异:
1、所有方法的参数传递都是传值的。
在 C#和delphi中都可以用一些关键字对参数进行修饰,使这些参数的传递方式变为传址而不是传值(delphi 中是out,C#中有ref 和 out),但java中没有这样的东西,所有的方法的参数传递方式都是传值。
在我刚知道了java的这一语言特性之后,感觉特别地不自在,后来细想一下,其实放弃了“传址”方式,也是有一定的好处的。需然放弃了它,使得在编写程序时少了一定的灵活性,然后没有了“传址”方式,程序员可以明确地知道自己的变量不会被其它函数所改变。使得程序的条理更加清晰在一个大项目的实现中,应该也是可以减少不少维护工作的。
2、关于数所类型,所有的数值类型都是有符号的
在C#和delphi中数值类型都有“有符号”与“无符号”之分。但在java中所有数据类型都是有符号的。并且数据一旦溢出也不是抛出异常。
这一点刚开始也是困扰了我很久。后来终于弄明白了,所谓的无符号数,实际上就是所二进制的符号位也看成是数据的一部份,而有符号数,是所二进制数的最高一位看成是符号位,用补码表示。
如果用4位二进制数表示一个数的话,无符号数的表示范围是0至15,有符号数的表示范围是 -8至7
当我们把9赋给一个4位的有符号数时,这个数就产生溢出,它的值成了-1(二进制1001)。
因此四位的无符号数9和有符号数-1,在计算机内的表示都是一样的。
因为java在不把数据溢出看成是异常,因此了解了以上的基本知识后,在一些情况中就可以所java中的有符号数据当作无符号数据进行处理了(主要是在逻辑运算的声合中可以这样处理)。
3 java中所有的方法默认都是虚方法(virtual)。
在c#和delphi中,虚方法是需要使用关键字virtual和override来明确注明的。
4 >>运算符是算术右移,而>>>才是逻辑右移。
算术右移是指在右移是,最左边补上“符号位”。而逻辑右移是指在右移时最左边补“0”。在C#和Delphi中好像没有算术右移的至少我现在还不知道有。
C#中的左移运算符(<<)和右移动算符(>>)
delphi中的左移运算符(shl)和右移动算符(shr)都是属于逻辑运行符。
刚学JAVA没多久,目前就先结到这里,目前对java的感觉是:
众所周知java和c#在很多地方都是很类似的,但是c#提供了一些语言特性使是编程时比较灵活,维护难度也跟java差不多,就我目前对java的认识,我觉得它之所以这么热也许就是因为它跨平台和有大量的开源项目支持了。其实我觉得如果C#也能跨平台的话,那它的潜力一定会比现在强很多。不过我也知道这是不可能的,呵呵...
符上今天练习做的MD5算法: