MD5 算法的java實現

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; 
 } 

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章