import java.io.*;
public class MD5{
int flength;//原报文长度
byte fbytes[];//原文件字节数组
byte sourcebytes[];//文件字节数组,其中包括补充的内容
int byteslength;//sourcebytes 长度
int sourceints[];//将字节数组转换为整数数组,这样一个整数是32位,满足分组需要
int intslength;//sourceints 长度
int numofteams;//分组个数
String resultmd5codes;//length=32
static int a0=0x67452301,b0=0xefcdab89,c0=0x98badcfe,d0=0x10325476;
int[] s={a0,b0,c0,d0};//链接量
int[] m=new int[16];//一组数据
公共函数
int bytesToint(byte[] b,int off){
return ((int)(b[off]&0xff)) |
((int)(b[off+1]&0xff) << 8) |
((int)(b[off+2]&0xff) << 16) |
((int)(b[off+3]&0xff) << 24);
}
void intTobytes(byte[] b, int off, int value) {
b[off+0] = (byte) (value & 0xff);
b[off+1] = (byte) ((value >> 8) & 0xff);
b[off+2] = (byte) ((value >> 16)& 0xff);
b[off+3] = (byte) ((value >> 24)& 0xff);
}
static String dumpBytes(byte[] bytes) {
int i;
StringBuffer sb = new StringBuffer();
for (i=0; i<bytes.length; i++) {
if (i%32 == 0 && i!=0) {
sb.append("/n");
}
String s = Integer.toHexString(bytes[i]);
if (s.length() < 2) {
s = "0"+s;
}
if (s.length() > 2) {
s = s.substring(s.length()-2);
}
sb.append(s);
}
return sb.toString();
}
//定义的运算函数
int f(int x,int y,int z){
return (x&y)|((~x)&z);
}
int g(int x,int y,int z){
return (x&z)|(y&(~z));
}
int h(int x,int y,int z){
return x^y^z;
}
int i(int x,int y,int z){
return y^(x|(~z));
}
int rotate_left (int x, int n){
return (x << n) | (x >>> (32-n)) ;
}
void ff(int an,int bn,int cn,int dn,int mj,int p,int ti){
s[an]=s[bn]+rotate_left((s[an]+f(s[bn],s[cn],s[dn])+mj+ti),p);
}
void gg(int an,int bn,int cn,int dn,int mj,int p,int ti){
s[an]=s[bn]+rotate_left((s[an]+g(s[bn],s[cn],s[dn])+mj+ti),p);
}
void hh(int an,int bn,int cn,int dn,int mj,int p,int ti){
s[an]=s[bn]+rotate_left((s[an]+h(s[bn],s[cn],s[dn])+mj+ti),p);
}
void ii(int an,int bn,int cn,int dn,int mj,int p,int ti){
s[an]=s[bn]+rotate_left((s[an]+i(s[bn],s[cn],s[dn])+mj+ti),p);
}
// 从文件得到字节数组,不包括最后附加的报文长度
void getFBytesFromFile(String filename)throws IOException{
/*File binaryFile = new File(filename);
FileInputStream instream = new FileInputStream(binaryFile);
flength=(int)binaryFile.length();
fbytes=new byte[flength];
instream.read(fbytes);
String tempstr=new String(fbytes,"GBK");
flength=tempstr.length();
fbytes=tempstr.getBytes();
instream.close(); */
StringBuffer buffer = new StringBuffer();
FileInputStream fis = new FileInputStream(filename);
InputStreamReader isr = new InputStreamReader(fis, "GB2312");
Reader in = new BufferedReader(isr);
int ch;
while ((ch = in.read()) > -1) {
buffer.append((char)ch);
}
in.close();
String tempstr=buffer.toString();
flength=tempstr.length();
fbytes=tempstr.getBytes();
}
//从字符串得到字节数组
void getFBytesFromString(String sourcestr){
flength=sourcestr.length();
fbytes=sourcestr.getBytes();
}
//填充字节数组
void paddingBytes(){
int yushu=flength%64;
if(yushu<56){
byteslength=flength+(56-yushu)+8;
}
else if(yushu>56){
byteslength=flength+(64+56-yushu)+8;
}
intslength=byteslength/4;
numofteams=intslength/16;
sourcebytes=new byte[byteslength];
for(int i=0;i<flength;i++)
sourcebytes[i]=fbytes[i];
sourcebytes[flength]=(byte)0x80;//填充'10000000'
for(int i=flength+1;i<byteslength-8;i++)//填充0
sourcebytes[i]=(byte)0x00;
long bits=(long)(flength*8);//64位表示的报文位长度
int lowbits = (int) bits;
int highbits = (int) (bits >>> 32);
int off=byteslength-8;
intTobytes(sourcebytes,off, lowbits);
off=byteslength-4;
intTobytes(sourcebytes,off, highbits);
System.out.println("flength:"+flength+",byteslength:"+byteslength+",intslength:"+intslength+",numofteams:"+numofteams);
}
//将字节数组转换为整数数组
void sourcebytesTosourceints(){
sourceints=new int[intslength];
for(int i=0;i<byteslength-4;i=i+4){
sourceints[i/4]=bytesToint(sourcebytes,i);
}
}
//下面为四轮转换
public void firstTurn(){
ff(0,1,2,3,m[0],7,0xd76aa478);
ff(3,0,1,2,m[1],12,0xe8c7b756);
ff(2,3,0,1,m[2],17,0x242070db);
ff(1,2,3,0,m[3],22,0xc1bdceee);
ff(0,1,2,3,m[4],7,0xf57c0faf);
ff(3,0,1,2,m[5],12,0x4787c62a);
ff(2,3,0,1,m[6],17,0xa8304613);
ff(1,2,3,0,m[7],22,0xfd469501);
ff(0,1,2,3,m[8],7,0x698098d8);
ff(3,0,1,2,m[9],12,0x8b44f7af);
ff(2,3,0,1,m[10],17,0xffff5bb1);
ff(1,2,3,0,m[11],22,0x895cd7be);
ff(0,1,2,3,m[12],7,0x6b901122);
ff(3,0,1,2,m[13],12,0xfd987193);
ff(2,3,0,1,m[14],17,0xa679438e);
ff(1,2,3,0,m[15],22,0x49b40821);
}
public void secondTurn(){
gg(0,1,2,3,m[1],5,0xf61e2562);
gg(3,0,1,2,m[6],9,0xc040b340);
gg(2,3,0,1,m[11],14,0x265e5a51);
gg(1,2,3,0,m[0],20,0xe9b6c7aa);
gg(0,1,2,3,m[5],5,0xd62f105d);
gg(3,0,1,2,m[10],9,0x02441453);
gg(2,3,0,1,m[15],14,0xd8a1e681);
gg(1,2,3,0,m[4],20,0xe7d3fbc8);
gg(0,1,2,3,m[9],5,0x21e1cde6);
gg(3,0,1,2,m[14],9,0xc33707d6);
gg(2,3,0,1,m[3],14,0xf4d50d87);
gg(1,2,3,0,m[8],20,0x455a14ed);
gg(0,1,2,3,m[13],5,0xa9e3e905);
gg(3,0,1,2,m[2],9,0xfcefa3f8);
gg(2,3,0,1,m[7],14,0x676f02d9);
gg(1,2,3,0,m[12],20,0x8d2a4c8a);
}
public void thirdTurn(){
hh(0,1,2,3,m[5],4,0xfffa3942);
hh(3,0,1,2,m[8],11,0x8771f681);
hh(2,3,0,1,m[11],16,0x6d9d6122);
hh(1,2,3,0,m[14],23,0xfde5380c);
hh(0,1,2,3,m[1],4,0xa4beea44);
hh(3,0,1,2,m[4],11,0x4bdecfa9);
hh(2,3,0,1,m[7],16,0xf6bb4b60);
hh(1,2,3,0,m[10],23,0xbebfbc70);
hh(0,1,2,3,m[13],4,0x289b7ec6);
hh(3,0,1,2,m[0],11,0xeaa127fa);
hh(2,3,0,1,m[3],16,0xd4ef3085);
hh(1,2,3,0,m[6],23,0x04881d05);
hh(0,1,2,3,m[9],4,0xd9d4d039) ;
hh(3,0,1,2,m[12],11,0xe6db99e5);
hh(2,3,0,1,m[15],16,0x1fa27cf8);
hh(1,2,3,0,m[2],23,0xc4ac5665);
}
public void fouthTurn(){
ii(0,1,2,3,m[0],6,0xf4292244);
ii(3,0,1,2,m[7],10,0x432aff97);
ii(2,3,0,1,m[14],15,0xab9423a7);
ii(1,2,3,0,m[5],21,0xfc93a039);
ii(0,1,2,3,m[12],6,0x655b59c3);
ii(3,0,1,2,m[3],10,0x8f0ccc92);
ii(2,3,0,1,m[10],15,0xffeff47d);
ii(1,2,3,0,m[1],21,0x85845dd1);
ii(0,1,2,3,m[8],6,0x6fa87e4f);
ii(3,0,1,2,m[15],10,0xfe2ce6e0);
ii(2,3,0,1,m[6],15,0xa3014314);
ii(1,2,3,0,m[13],21,0x4e0811a1);
ii(0,1,2,3,m[4],6,0xf7537e82);
ii(3,0,1,2,m[11],10,0xbd3af235);
ii(2,3,0,1,m[2],15,0x2ad7d2bb);
ii(1,2,3,0,m[9],21,0xeb86d391);
}
//对第num组数剧的转换.
public void forOneTeam(int num){
int a,b,c,d;
a=s[0];
b=s[1];
c=s[2];
d=s[3];
//用本组数据初始化m[16]
for(int i=0;i<16;i++){
m[i]=sourceints[16*num+i];
}
firstTurn();
secondTurn();
thirdTurn();
fouthTurn();
s[0]+=a;
s[1]+=b;
s[2]+=c;
s[3]+=d;
}
//对每组数据一次处理
void everyTeam(){
for(int i=0;i<numofteams;i++){
forOneTeam(i);
}
}
//得到最后的MD5编码
void getMD5CodesString(){
byte[] digest=new byte[16];
intTobytes(digest, 0, s[0]);
intTobytes(digest, 4, s[1]);
intTobytes(digest, 8, s[2]);
intTobytes(digest, 12, s[3]);
resultmd5codes=dumpBytes(digest);
}
//译码的过程
void md5Encode(){
paddingBytes();
sourcebytesTosourceints();
everyTeam();
getMD5CodesString();
}
//对字符串编码
public String md5EncodeString(String sourcestr){
getFBytesFromString(sourcestr);
md5Encode();
return resultmd5codes;
}
//对文件编码
public String md5EncodeFile(String filename)throws IOException{
getFBytesFromFile(filename);
md5Encode();
return resultmd5codes;
}
}