MD5算法原理
 MD5(单向散列算法)的全称是Message-Digest
 Algorithm 5(信息-摘要算法),经MD2、MD3和MD4发展而来。MD5算法的使用不须要支付不论什么版权费用。
MD5功能:
输入随意长度的信息,经过处理,输出为128位的信息(数字指纹);
不同的输入得到的不同的结果(唯一性);
依据128位的输出结果不可能反推出输入的信息(不可逆);
MD5属不属于加密算法:
觉得不属于的人是由于他们觉得不能从密文(散列值)反过来得到原文,即没有解密算法,所以这部分人觉得MD5仅仅能属于算法,不能称为加密算法;
觉得属于的人是由于他们觉得经过MD5处理后看不到原文,即已经将原文加密,所以觉得MD5属于加密算法;我个人支持后者。
MD5用途:
1、防止被篡改:
1)比方发送一个电子文档,发送前,我先得到MD5的输出结果a。然后在对方收到电子文档后,对方也得到一个MD5的输出结果b。假设a与b一样就代表中途未被篡改。2)比方我提供文件下载,为了防止不法分子在安装程序中加入木马,我能够在站点上发布由安装文件得到的MD5输出结果。3)SVN在检測文件是否在CheckOut后被改动过,也是用到了MD5.
2、防止直接看到明文:
如今非常多站点在数据库存储用户的password的时候都是存储用户password的MD5值。这样就算不法分子得到数据库的用户password的MD5值,也无法知道用户的password(事实上这样是不安全的,后面我会提到)。(比方在UNIX系统中用户的password就是以MD5(或其他类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的password计算成MD5值,然后再去和保存在文件系统中的MD5值进行比較,进而确定输入的password是否正确。通过这种步骤,系统在并不知道用户password的明码的情况下就能够确定用户登录系统的合法性。这不但能够避免用户的password被具有系统管理员权限的用户知道,并且还在一定程度上添加了password被破解的难度。)
3、防止抵赖(数字签名):
这须要一个第三方认证机构。比如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。若以后A说这文件不是他写的,权威机构仅仅需对此文件又一次产生摘要信息,然后跟记录在冊的摘要信息进行比对,同样的话,就证明是A写的了。这就是所谓的“数字签名”。
MD5算法过程:
对MD5算法简要的叙述能够为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
第一步、填充:假设输入信息的长度(bit)对512求余的结果不等于448,就须要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);
第二步、记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。
第三步、装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。假设在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有点晕哈,事实上想一想就明确了。
第四步、四轮循环运算:循环的次数是分组的个数(N+1)
1)将每一512字节细分成16个小组,每一个小组64位(8个字节)
     
2)先认识四个线性函数(&是与,|是或,~是非,^是异或)
3)设Mj表示消息的第j个子分组(从0到15),<<<s表示循环左移s位,则四种操作为:
4)四轮运算
5)每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环。
 
假设上面的过程用JAVA代码来实现的话,代码例如以下:
 package woxingwosu;
package woxingwosu;


 /************************************************
/************************************************
 * MD5 算法
 * MD5 算法
 * @author 我行我素
 * @author 我行我素
 * @Date 2007-07-01
 * @Date 2007-07-01
 *************************************************/
*************************************************/
 public class MD5 {
public class MD5 {

 static final String hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
    static final String hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
 //标准的幻数
    //标准的幻数
 private static final long A=0x67452301L;
    private static final long A=0x67452301L;
 private static final long B=0xefcdab89L;
    private static final long B=0xefcdab89L;
 private static final long C=0x98badcfeL;
    private static final long C=0x98badcfeL;
 private static final long D=0x10325476L;
    private static final long D=0x10325476L;

 
    
 //以下这些S11-S44实际上是一个4*4的矩阵,在四轮循环运算中用到
    //以下这些S11-S44实际上是一个4*4的矩阵,在四轮循环运算中用到
 static final int S11 = 7;
    static final int S11 = 7;
 static final int S12 = 12;
    static final int S12 = 12;
 static final int S13 = 17;
    static final int S13 = 17;
 static final int S14 = 22;
    static final int S14 = 22;

 static final int S21 = 5;
    static final int S21 = 5;
 static final int S22 = 9;
    static final int S22 = 9;
 static final int S23 = 14;
    static final int S23 = 14;
 static final int S24 = 20;
    static final int S24 = 20;

 static final int S31 = 4;
    static final int S31 = 4;
 static final int S32 = 11;
    static final int S32 = 11;
 static final int S33 = 16;
    static final int S33 = 16;
 static final int S34 = 23;
    static final int S34 = 23;

 static final int S41 = 6;
    static final int S41 = 6;
 static final int S42 = 10;
    static final int S42 = 10;
 static final int S43 = 15;
    static final int S43 = 15;
 static final int S44 = 21;
    static final int S44 = 21;
 
    
 //java不支持无符号的基本数据(unsigned)
    //java不支持无符号的基本数据(unsigned)
 private long [] result={A,B,C,D};//存储hash结果,共4×32=128位,初始化值为(幻数的级联)
    private long [] result={A,B,C,D};//存储hash结果,共4×32=128位,初始化值为(幻数的级联)
 
    
 public static void main(String []args){
    public static void main(String []args){
 MD5 md=new MD5();
        MD5 md=new MD5();
 System.out.println("md5(abc)="+md.digest("abc"));
        System.out.println("md5(abc)="+md.digest("abc"));
 }
    }
 
    
 private String digest(String inputStr){
    private String digest(String inputStr){
 byte [] inputBytes=inputStr.getBytes();
        byte [] inputBytes=inputStr.getBytes();
 int byteLen=inputBytes.length;//长度(字节)
        int byteLen=inputBytes.length;//长度(字节)
 int groupCount=0;//完整分组的个数
        int groupCount=0;//完整分组的个数
 groupCount=byteLen/64;//每组512位(64字节)
        groupCount=byteLen/64;//每组512位(64字节)
 long []groups=null;//每一个小组(64字节)再细分后的16个小组(4字节)
        long []groups=null;//每一个小组(64字节)再细分后的16个小组(4字节)
 
        
 //处理每个完整 分组
        //处理每个完整 分组
 for(int step=0;step<groupCount;step++){
        for(int step=0;step<groupCount;step++){
 groups=divGroup(inputBytes,step*64);
            groups=divGroup(inputBytes,step*64);
 trans(groups);//处理分组,核心算法
            trans(groups);//处理分组,核心算法
 }
        }
 
        
 //处理完整分组后的尾巴
        //处理完整分组后的尾巴
 int rest=byteLen%64;//512位分组后的余数
        int rest=byteLen%64;//512位分组后的余数
 byte [] tempBytes=new byte[64];
        byte [] tempBytes=new byte[64];
 if(rest<=56){
        if(rest<=56){
 for(int i=0;i<rest;i++)
            for(int i=0;i<rest;i++)
 tempBytes[i]=inputBytes[byteLen-rest+i];
                tempBytes[i]=inputBytes[byteLen-rest+i];
 if(rest<56){
            if(rest<56){
 tempBytes[rest]=(byte)(1<<7);
                tempBytes[rest]=(byte)(1<<7);
 for(int i=1;i<56-rest;i++)
                for(int i=1;i<56-rest;i++)
 tempBytes[rest+i]=0;
                    tempBytes[rest+i]=0;
 }
            }
 long len=(long)(byteLen<<3);
            long len=(long)(byteLen<<3);
 for(int i=0;i<8;i++){
            for(int i=0;i<8;i++){
 tempBytes[56+i]=(byte)(len&0xFFL);
                tempBytes[56+i]=(byte)(len&0xFFL);
 len=len>>8;
                len=len>>8;
 }
            }
 groups=divGroup(tempBytes,0);
            groups=divGroup(tempBytes,0);
 trans(groups);//处理分组
            trans(groups);//处理分组
 }else{
        }else{
 for(int i=0;i<rest;i++)
            for(int i=0;i<rest;i++)
 tempBytes[i]=inputBytes[byteLen-rest+i];
                tempBytes[i]=inputBytes[byteLen-rest+i];
 tempBytes[rest]=(byte)(1<<7);
            tempBytes[rest]=(byte)(1<<7);
 for(int i=rest+1;i<64;i++)
            for(int i=rest+1;i<64;i++)
 tempBytes[i]=0;
                tempBytes[i]=0;
 groups=divGroup(tempBytes,0);
            groups=divGroup(tempBytes,0);
 trans(groups);//处理分组
            trans(groups);//处理分组
 
            
 for(int i=0;i<56;i++)
            for(int i=0;i<56;i++)
 tempBytes[i]=0;
                tempBytes[i]=0;
 long len=(long)(byteLen<<3);
            long len=(long)(byteLen<<3);
 for(int i=0;i<8;i++){
            for(int i=0;i<8;i++){
 tempBytes[56+i]=(byte)(len&0xFFL);
                tempBytes[56+i]=(byte)(len&0xFFL);
 len=len>>8;
                len=len>>8;
 }
            }
 groups=divGroup(tempBytes,0);
            groups=divGroup(tempBytes,0);
 trans(groups);//处理分组
            trans(groups);//处理分组
 }
        }
 
        
 //将Hash值转换成十六进制的字符串
        //将Hash值转换成十六进制的字符串
 String resStr="";
        String resStr="";
 long temp=0;
        long temp=0;
 for(int i=0;i<4;i++){
        for(int i=0;i<4;i++){
 for(int j=0;j<4;j++){
            for(int j=0;j<4;j++){
 temp=result[i]&0x0FL;
                temp=result[i]&0x0FL;
 String a=hexs[(int)(temp)];
                String a=hexs[(int)(temp)];
 result[i]=result[i]>>4;
                result[i]=result[i]>>4;
 temp=result[i]&0x0FL;
                temp=result[i]&0x0FL;
 resStr+=hexs[(int)(temp)]+a;
                resStr+=hexs[(int)(temp)]+a;
 result[i]=result[i]>>4;
                result[i]=result[i]>>4;
 }
            }
 }
        }
 return resStr;
        return resStr;
 }
    }
 
    
 /**
    /**
 * 从inputBytes的index開始取512位,作为新的分组
     * 从inputBytes的index開始取512位,作为新的分组
 * 将每个512位的分组再细分成16个小组,每个小组64位(8个字节)
     * 将每个512位的分组再细分成16个小组,每个小组64位(8个字节)
 * @param inputBytes
     * @param inputBytes
 * @param index
     * @param index
 * @return
     * @return
 */
     */
 private static long[] divGroup(byte[] inputBytes,int index){
    private static long[] divGroup(byte[] inputBytes,int index){
 long [] temp=new long[16];
        long [] temp=new long[16];
 for(int i=0;i<16;i++){
        for(int i=0;i<16;i++){
 temp[i]=b2iu(inputBytes[4*i+index])|
            temp[i]=b2iu(inputBytes[4*i+index])|
 (b2iu(inputBytes[4*i+1+index]))<<8|
                (b2iu(inputBytes[4*i+1+index]))<<8|
 (b2iu(inputBytes[4*i+2+index]))<<16|
                (b2iu(inputBytes[4*i+2+index]))<<16|
 (b2iu(inputBytes[4*i+3+index]))<<24;
                (b2iu(inputBytes[4*i+3+index]))<<24;
 }
        }
 return temp;
        return temp;
 }
    }
 
    
 /**
    /**
 * 这时不存在符号位(符号位存储不再是代表正负),所以须要处理一下
     * 这时不存在符号位(符号位存储不再是代表正负),所以须要处理一下
 * @param b
     * @param b
 * @return
     * @return
 */
     */
 public static long b2iu(byte b){
    public static long b2iu(byte b){
 return b < 0 ? b & 0x7F + 128 : b;
        return b < 0 ? b & 0x7F + 128 : b;
 }
     }
 
    
 /**
    /**
 * 基本的操作,四轮循环
     * 基本的操作,四轮循环
 * @param groups[]--每个分组512位(64字节)
     * @param groups[]--每个分组512位(64字节)
 */
     */
 private void trans(long[] groups) {
    private void trans(long[] groups) {
 long a = result[0], b = result[1], c = result[2], d = result[3];
        long a = result[0], b = result[1], c = result[2], d = result[3];
 /*第一轮*/
        /*第一轮*/
 a = FF(a, b, c, d, groups[0], S11, 0xd76aa478L); /* 1 */
        a = FF(a, b, c, d, groups[0], S11, 0xd76aa478L); /* 1 */
 d = FF(d, a, b, c, groups[1], S12, 0xe8c7b756L); /* 2 */
        d = FF(d, a, b, c, groups[1], S12, 0xe8c7b756L); /* 2 */
 c = FF(c, d, a, b, groups[2], S13, 0x242070dbL); /* 3 */
        c = FF(c, d, a, b, groups[2], S13, 0x242070dbL); /* 3 */
 b = FF(b, c, d, a, groups[3], S14, 0xc1bdceeeL); /* 4 */
        b = FF(b, c, d, a, groups[3], S14, 0xc1bdceeeL); /* 4 */
 a = FF(a, b, c, d, groups[4], S11, 0xf57c0fafL); /* 5 */
        a = FF(a, b, c, d, groups[4], S11, 0xf57c0fafL); /* 5 */
 d = FF(d, a, b, c, groups[5], S12, 0x4787c62aL); /* 6 */
        d = FF(d, a, b, c, groups[5], S12, 0x4787c62aL); /* 6 */
 c = FF(c, d, a, b, groups[6], S13, 0xa8304613L); /* 7 */
        c = FF(c, d, a, b, groups[6], S13, 0xa8304613L); /* 7 */
 b = FF(b, c, d, a, groups[7], S14, 0xfd469501L); /* 8 */
        b = FF(b, c, d, a, groups[7], S14, 0xfd469501L); /* 8 */
 a = FF(a, b, c, d, groups[8], S11, 0x698098d8L); /* 9 */
        a = FF(a, b, c, d, groups[8], S11, 0x698098d8L); /* 9 */
 d = FF(d, a, b, c, groups[9], S12, 0x8b44f7afL); /* 10 */
        d = FF(d, a, b, c, groups[9], S12, 0x8b44f7afL); /* 10 */
 c = FF(c, d, a, b, groups[10], S13, 0xffff5bb1L); /* 11 */
        c = FF(c, d, a, b, groups[10], S13, 0xffff5bb1L); /* 11 */
 b = FF(b, c, d, a, groups[11], S14, 0x895cd7beL); /* 12 */
        b = FF(b, c, d, a, groups[11], S14, 0x895cd7beL); /* 12 */
 a = FF(a, b, c, d, groups[12], S11, 0x6b901122L); /* 13 */
        a = FF(a, b, c, d, groups[12], S11, 0x6b901122L); /* 13 */
 d = FF(d, a, b, c, groups[13], S12, 0xfd987193L); /* 14 */
        d = FF(d, a, b, c, groups[13], S12, 0xfd987193L); /* 14 */
 c = FF(c, d, a, b, groups[14], S13, 0xa679438eL); /* 15 */
        c = FF(c, d, a, b, groups[14], S13, 0xa679438eL); /* 15 */
 b = FF(b, c, d, a, groups[15], S14, 0x49b40821L); /* 16 */
        b = FF(b, c, d, a, groups[15], S14, 0x49b40821L); /* 16 */

 /*第二轮*/
        /*第二轮*/
 a = GG(a, b, c, d, groups[1], S21, 0xf61e2562L); /* 17 */
        a = GG(a, b, c, d, groups[1], S21, 0xf61e2562L); /* 17 */
 d = GG(d, a, b, c, groups[6], S22, 0xc040b340L); /* 18 */
        d = GG(d, a, b, c, groups[6], S22, 0xc040b340L); /* 18 */
 c = GG(c, d, a, b, groups[11], S23, 0x265e5a51L); /* 19 */
        c = GG(c, d, a, b, groups[11], S23, 0x265e5a51L); /* 19 */
 b = GG(b, c, d, a, groups[0], S24, 0xe9b6c7aaL); /* 20 */
        b = GG(b, c, d, a, groups[0], S24, 0xe9b6c7aaL); /* 20 */
 a = GG(a, b, c, d, groups[5], S21, 0xd62f105dL); /* 21 */
        a = GG(a, b, c, d, groups[5], S21, 0xd62f105dL); /* 21 */
 d = GG(d, a, b, c, groups[10], S22, 0x2441453L); /* 22 */
        d = GG(d, a, b, c, groups[10], S22, 0x2441453L); /* 22 */
 c = GG(c, d, a, b, groups[15], S23, 0xd8a1e681L); /* 23 */
        c = GG(c, d, a, b, groups[15], S23, 0xd8a1e681L); /* 23 */
 b = GG(b, c, d, a, groups[4], S24, 0xe7d3fbc8L); /* 24 */
        b = GG(b, c, d, a, groups[4], S24, 0xe7d3fbc8L); /* 24 */
 a = GG(a, b, c, d, groups[9], S21, 0x21e1cde6L); /* 25 */
        a = GG(a, b, c, d, groups[9], S21, 0x21e1cde6L); /* 25 */
 d = GG(d, a, b, c, groups[14], S22, 0xc33707d6L); /* 26 */
        d = GG(d, a, b, c, groups[14], S22, 0xc33707d6L); /* 26 */
 c = GG(c, d, a, b, groups[3], S23, 0xf4d50d87L); /* 27 */
        c = GG(c, d, a, b, groups[3], S23, 0xf4d50d87L); /* 27 */
 b = GG(b, c, d, a, groups[8], S24, 0x455a14edL); /* 28 */
        b = GG(b, c, d, a, groups[8], S24, 0x455a14edL); /* 28 */
 a = GG(a, b, c, d, groups[13], S21, 0xa9e3e905L); /* 29 */
        a = GG(a, b, c, d, groups[13], S21, 0xa9e3e905L); /* 29 */
 d = GG(d, a, b, c, groups[2], S22, 0xfcefa3f8L); /* 30 */
        d = GG(d, a, b, c, groups[2], S22, 0xfcefa3f8L); /* 30 */
 c = GG(c, d, a, b, groups[7], S23, 0x676f02d9L); /* 31 */
        c = GG(c, d, a, b, groups[7], S23, 0x676f02d9L); /* 31 */
 b = GG(b, c, d, a, groups[12], S24, 0x8d2a4c8aL); /* 32 */
        b = GG(b, c, d, a, groups[12], S24, 0x8d2a4c8aL); /* 32 */

 /*第三轮*/
        /*第三轮*/
 a = HH(a, b, c, d, groups[5], S31, 0xfffa3942L); /* 33 */
        a = HH(a, b, c, d, groups[5], S31, 0xfffa3942L); /* 33 */
 d = HH(d, a, b, c, groups[8], S32, 0x8771f681L); /* 34 */
        d = HH(d, a, b, c, groups[8], S32, 0x8771f681L); /* 34 */
 c = HH(c, d, a, b, groups[11], S33, 0x6d9d6122L); /* 35 */
        c = HH(c, d, a, b, groups[11], S33, 0x6d9d6122L); /* 35 */
 b = HH(b, c, d, a, groups[14], S34, 0xfde5380cL); /* 36 */
        b = HH(b, c, d, a, groups[14], S34, 0xfde5380cL); /* 36 */
 a = HH(a, b, c, d, groups[1], S31, 0xa4beea44L); /* 37 */
        a = HH(a, b, c, d, groups[1], S31, 0xa4beea44L); /* 37 */
 d = HH(d, a, b, c, groups[4], S32, 0x4bdecfa9L); /* 38 */
        d = HH(d, a, b, c, groups[4], S32, 0x4bdecfa9L); /* 38 */
 c = HH(c, d, a, b, groups[7], S33, 0xf6bb4b60L); /* 39 */
        c = HH(c, d, a, b, groups[7], S33, 0xf6bb4b60L); /* 39 */
 b = HH(b, c, d, a, groups[10], S34, 0xbebfbc70L); /* 40 */
        b = HH(b, c, d, a, groups[10], S34, 0xbebfbc70L); /* 40 */
 a = HH(a, b, c, d, groups[13], S31, 0x289b7ec6L); /* 41 */
        a = HH(a, b, c, d, groups[13], S31, 0x289b7ec6L); /* 41 */
 d = HH(d, a, b, c, groups[0], S32, 0xeaa127faL); /* 42 */
        d = HH(d, a, b, c, groups[0], S32, 0xeaa127faL); /* 42 */
 c = HH(c, d, a, b, groups[3], S33, 0xd4ef3085L); /* 43 */
        c = HH(c, d, a, b, groups[3], S33, 0xd4ef3085L); /* 43 */
 b = HH(b, c, d, a, groups[6], S34, 0x4881d05L); /* 44 */
        b = HH(b, c, d, a, groups[6], S34, 0x4881d05L); /* 44 */
 a = HH(a, b, c, d, groups[9], S31, 0xd9d4d039L); /* 45 */
        a = HH(a, b, c, d, groups[9], S31, 0xd9d4d039L); /* 45 */
 d = HH(d, a, b, c, groups[12], S32, 0xe6db99e5L); /* 46 */
        d = HH(d, a, b, c, groups[12], S32, 0xe6db99e5L); /* 46 */
 c = HH(c, d, a, b, groups[15], S33, 0x1fa27cf8L); /* 47 */
        c = HH(c, d, a, b, groups[15], S33, 0x1fa27cf8L); /* 47 */
 b = HH(b, c, d, a, groups[2], S34, 0xc4ac5665L); /* 48 */
        b = HH(b, c, d, a, groups[2], S34, 0xc4ac5665L); /* 48 */

 /*第四轮*/
        /*第四轮*/
 a = II(a, b, c, d, groups[0], S41, 0xf4292244L); /* 49 */
        a = II(a, b, c, d, groups[0], S41, 0xf4292244L); /* 49 */
 d = II(d, a, b, c, groups[7], S42, 0x432aff97L); /* 50 */
        d = II(d, a, b, c, groups[7], S42, 0x432aff97L); /* 50 */
 c = II(c, d, a, b, groups[14], S43, 0xab9423a7L); /* 51 */
        c = II(c, d, a, b, groups[14], S43, 0xab9423a7L); /* 51 */
 b = II(b, c, d, a, groups[5], S44, 0xfc93a039L); /* 52 */
        b = II(b, c, d, a, groups[5], S44, 0xfc93a039L); /* 52 */
 a = II(a, b, c, d, groups[12], S41, 0x655b59c3L); /* 53 */
        a = II(a, b, c, d, groups[12], S41, 0x655b59c3L); /* 53 */
 d = II(d, a, b, c, groups[3], S42, 0x8f0ccc92L); /* 54 */
        d = II(d, a, b, c, groups[3], S42, 0x8f0ccc92L); /* 54 */
 c = II(c, d, a, b, groups[10], S43, 0xffeff47dL); /* 55 */
        c = II(c, d, a, b, groups[10], S43, 0xffeff47dL); /* 55 */
 b = II(b, c, d, a, groups[1], S44, 0x85845dd1L); /* 56 */
        b = II(b, c, d, a, groups[1], S44, 0x85845dd1L); /* 56 */
 a = II(a, b, c, d, groups[8], S41, 0x6fa87e4fL); /* 57 */
        a = II(a, b, c, d, groups[8], S41, 0x6fa87e4fL); /* 57 */
 d = II(d, a, b, c, groups[15], S42, 0xfe2ce6e0L); /* 58 */
        d = II(d, a, b, c, groups[15], S42, 0xfe2ce6e0L); /* 58 */
 c = II(c, d, a, b, groups[6], S43, 0xa3014314L); /* 59 */
        c = II(c, d, a, b, groups[6], S43, 0xa3014314L); /* 59 */
 b = II(b, c, d, a, groups[13], S44, 0x4e0811a1L); /* 60 */
        b = II(b, c, d, a, groups[13], S44, 0x4e0811a1L); /* 60 */
 a = II(a, b, c, d, groups[4], S41, 0xf7537e82L); /* 61 */
        a = II(a, b, c, d, groups[4], S41, 0xf7537e82L); /* 61 */
 d = II(d, a, b, c, groups[11], S42, 0xbd3af235L); /* 62 */
        d = II(d, a, b, c, groups[11], S42, 0xbd3af235L); /* 62 */
 c = II(c, d, a, b, groups[2], S43, 0x2ad7d2bbL); /* 63 */
        c = II(c, d, a, b, groups[2], S43, 0x2ad7d2bbL); /* 63 */
 b = II(b, c, d, a, groups[9], S44, 0xeb86d391L); /* 64 */
        b = II(b, c, d, a, groups[9], S44, 0xeb86d391L); /* 64 */

 /*增加到之前计算的结果其中*/
        /*增加到之前计算的结果其中*/
 result[0] += a;
        result[0] += a;
 result[1] += b;
        result[1] += b;
 result[2] += c;
        result[2] += c;
 result[3] += d;
        result[3] += d;
 result[0]=result[0]&0xFFFFFFFFL;
        result[0]=result[0]&0xFFFFFFFFL;
 result[1]=result[1]&0xFFFFFFFFL;
        result[1]=result[1]&0xFFFFFFFFL;
 result[2]=result[2]&0xFFFFFFFFL;
        result[2]=result[2]&0xFFFFFFFFL;
 result[3]=result[3]&0xFFFFFFFFL;
        result[3]=result[3]&0xFFFFFFFFL;
 }
    }
 
    
 /**
    /**
 * 以下是处理要用到的线性函数
     * 以下是处理要用到的线性函数
 */
     */
 private static long F(long x, long y, long z) {
    private static long F(long x, long y, long z) {
 return (x & y) | ((~x) & z);
        return (x & y) | ((~x) & z);
 }
    }

 private static long G(long x, long y, long z) {
    private static long G(long x, long y, long z) {
 return (x & z) | (y & (~z));
        return (x & z) | (y & (~z));
 }
    }

 private static long H(long x, long y, long z) {
    private static long H(long x, long y, long z) {
 return x ^ y ^ z;
        return x ^ y ^ z;
 }
    }

 private static long I(long x, long y, long z) {
    private static long I(long x, long y, long z) {
 return y ^ (x | (~z));
        return y ^ (x | (~z));
 }
    }

 private static long FF(long a, long b, long c, long d, long x, long s,
    private static long FF(long a, long b, long c, long d, long x, long s,
 long ac) {
            long ac) {
 a += (F(b, c, d)&0xFFFFFFFFL) + x + ac;
        a += (F(b, c, d)&0xFFFFFFFFL) + x + ac;
 a = ((a&0xFFFFFFFFL)<< s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a = ((a&0xFFFFFFFFL)<< s) | ((a&0xFFFFFFFFL) >>> (32 - s));
 a += b;
        a += b;
 return (a&0xFFFFFFFFL);
        return (a&0xFFFFFFFFL);
 }
    }

 private static long GG(long a, long b, long c, long d, long x, long s,
    private static long GG(long a, long b, long c, long d, long x, long s,
 long ac) {
            long ac) {
 a += (G(b, c, d)&0xFFFFFFFFL) + x + ac;
        a += (G(b, c, d)&0xFFFFFFFFL) + x + ac;
 a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
 a += b;
        a += b;
 return (a&0xFFFFFFFFL);
        return (a&0xFFFFFFFFL);
 }
    }

 private static long HH(long a, long b, long c, long d, long x, long s,
    private static long HH(long a, long b, long c, long d, long x, long s,
 long ac) {
            long ac) {
 a += (H(b, c, d)&0xFFFFFFFFL) + x + ac;
        a += (H(b, c, d)&0xFFFFFFFFL) + x + ac;
 a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
 a += b;
        a += b;
 return (a&0xFFFFFFFFL);
        return (a&0xFFFFFFFFL);
 }
    }

 private static long II(long a, long b, long c, long d, long x, long s,
    private static long II(long a, long b, long c, long d, long x, long s,
 long ac) {
            long ac) {
 a += (I(b, c, d)&0xFFFFFFFFL) + x + ac;
        a += (I(b, c, d)&0xFFFFFFFFL) + x + ac;
 a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
 a += b;
        a += b;
 return (a&0xFFFFFFFFL);
        return (a&0xFFFFFFFFL);
 }
    }
 }
}
 MD5安全性:
MD5安全性:
普遍觉得MD5是非常安全,由于暴力破解的时间是一般人无法接受的。实际上假设把用户的passwordMD5处理后再存储到数据库,事实上是非常不安全的。由于用户的password是比較短的,并且非常多用户的password都使用生日,手机号码,身份证号码,电话号码等等。或者使用经常使用的一些吉利的数字,或者某个英文单词。假设我把经常使用的password先MD5处理,把数据存储起来,然后再跟你的MD5结果匹配,这时我就有可能得到明文。比方某个MD5破解站点http://www.cmd5.com/default.aspx,我把其站点下的公告复制例如以下
我认为仅仅须要将上面我写的MD5的标准幻数A,B,C,D的值改动一下,改动后也不是MD5算法了,由于不能保证唯一性。这样就算别人得到32位的值,他假设不知道幻数的值是无法还原明文的。就算得到了幻数,也是非常难破解的。
JAVA实现MD5
在java中实现MD5是非常easy的,在包java.security有个类MessageDigest。官方文档例如以下
 package woxingwosu;
package woxingwosu;
 /************************************************
/************************************************
 * MD5 算法
 * MD5 算法
 * @author 我行我素
 * @author 我行我素
 * @Date 2007-07-06
 * @Date 2007-07-06
 *************************************************/
*************************************************/
 import java.security.MessageDigest;
import java.security.MessageDigest;

 public class MyMD5 {
public class MyMD5 {

 static char[] hex = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    static char[] hex = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 
 public static void main(String[] args) {
    public static void main(String[] args) {
 try{
        try{
 MessageDigest md5 = MessageDigest.getInstance("MD5");//申明使用MD5算法
            MessageDigest md5 = MessageDigest.getInstance("MD5");//申明使用MD5算法
 md5.update("a".getBytes());//
            md5.update("a".getBytes());//
 System.out.println("md5(a)="+byte2str(md5.digest()));
            System.out.println("md5(a)="+byte2str(md5.digest()));
 md5.update("a".getBytes());
            md5.update("a".getBytes());
 md5.update("bc".getBytes());
            md5.update("bc".getBytes());
 System.out.println("md5(abc)="+byte2str(md5.digest()));
            System.out.println("md5(abc)="+byte2str(md5.digest()));
 }catch(Exception e){
        }catch(Exception e){
 e.printStackTrace();
            e.printStackTrace();
 }
        }
 }
    }
 
    
 /**
    /**
 * 将字节数组转换成十六进制字符串
     * 将字节数组转换成十六进制字符串
 * @param bytes
     * @param bytes
 * @return
     * @return
 */
     */
 private static String byte2str(byte []bytes){
    private static String byte2str(byte []bytes){
 int len = bytes.length;
        int len = bytes.length;   
 StringBuffer result = new StringBuffer();
        StringBuffer result = new StringBuffer();    
 for (int i = 0; i < len; i++) {
        for (int i = 0; i < len; i++) {   
 byte byte0 = bytes[i];
            byte byte0 = bytes[i];   
 result.append(hex[byte0 >>> 4 & 0xf]);
            result.append(hex[byte0 >>> 4 & 0xf]);   
 result.append(hex[byte0 & 0xf]);
            result.append(hex[byte0 & 0xf]);   
 }
        }
 return result.toString();
        return result.toString();
 }
    }
 }
} 
 另外附上其它版本号的MD5算法的实现(来自网络)
  另外附上其它版本号的MD5算法的实现(来自网络)
1)JS版的MD5(调用方法:md5(明文))
 /*
/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */
 */

 /*
/*
 * Configurable variables. You may need to tweak these to be compatible with
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 * the server-side, but the defaults work in most cases.
 */
 */
 var hexcase = 1;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var hexcase = 1;  /* hex output format. 0 - lowercase; 1 - uppercase        */
 var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
 var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

 /*
/*
 * These are the functions you'll usually want to call
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 * They take string arguments and return either hex or base-64 encoded strings
 */
 */
 function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
 function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
 function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
 function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }

 /*
/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
 */
 function core_md5(x, len)
function core_md5(x, len)
 {
{
 /* append padding */
  /* append padding */
 x[len >> 5] |= 0x80 << ((len) % 32);
  x[len >> 5] |= 0x80 << ((len) % 32);
 x[(((len + 64) >>> 9) << 4) + 14] = len;
  x[(((len + 64) >>> 9) << 4) + 14] = len;

 var a =  1732584193;
  var a =  1732584193;
 var b = -271733879;
  var b = -271733879;
 var c = -1732584194;
  var c = -1732584194;
 var d =  271733878;
  var d =  271733878;

 for(var i = 0; i < x.length; i += 16)
  for(var i = 0; i < x.length; i += 16)
 {
  {
 var olda = a;
    var olda = a;
 var oldb = b;
    var oldb = b;
 var oldc = c;
    var oldc = c;
 var oldd = d;
    var oldd = d;

 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
 c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
 d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
 a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
 c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
 a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
 b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
 c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
 d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
 a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
 b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
 c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
 c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
 d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
 a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
 b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
 c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
 d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
 a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
 a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
 b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
 c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

 a = safe_add(a, olda);
    a = safe_add(a, olda);
 b = safe_add(b, oldb);
    b = safe_add(b, oldb);
 c = safe_add(c, oldc);
    c = safe_add(c, oldc);
 d = safe_add(d, oldd);
    d = safe_add(d, oldd);
 }
  }
 return Array(a, b, c, d);
  return Array(a, b, c, d);

 }
}

 /*
/*
 * These functions implement the four basic operations the algorithm uses.
 * These functions implement the four basic operations the algorithm uses.
 */
 */
 function md5_cmn(q, a, b, x, s, t)
function md5_cmn(q, a, b, x, s, t)
 {
{
 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
 }
}
 function md5_ff(a, b, c, d, x, s, t)
function md5_ff(a, b, c, d, x, s, t)
 {
{
 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
 }
}
 function md5_gg(a, b, c, d, x, s, t)
function md5_gg(a, b, c, d, x, s, t)
 {
{
 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
 }
}
 function md5_hh(a, b, c, d, x, s, t)
function md5_hh(a, b, c, d, x, s, t)
 {
{
 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
 }
}
 function md5_ii(a, b, c, d, x, s, t)
function md5_ii(a, b, c, d, x, s, t)
 {
{
 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
 }
}

 /*
/*
 * Calculate the HMAC-MD5, of a key and some data
 * Calculate the HMAC-MD5, of a key and some data
 */
 */
 function core_hmac_md5(key, data)
function core_hmac_md5(key, data)
 {
{
 var bkey = str2binl(key);
  var bkey = str2binl(key);
 if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

 var ipad = Array(16), opad = Array(16);
  var ipad = Array(16), opad = Array(16);
 for(var i = 0; i < 16; i++)
  for(var i = 0; i < 16; i++)
 {
  {
 ipad[i] = bkey[i] ^ 0x36363636;
    ipad[i] = bkey[i] ^ 0x36363636;
 opad[i] = bkey[i] ^ 0x5C5C5C5C;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
 }
  }

 var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
 return core_md5(opad.concat(hash), 512 + 128);
  return core_md5(opad.concat(hash), 512 + 128);
 }
}

 /*
/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 * to work around bugs in some JS interpreters.
 */
 */
 function safe_add(x, y)
function safe_add(x, y)
 {
{
 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
 return (msw << 16) | (lsw & 0xFFFF);
  return (msw << 16) | (lsw & 0xFFFF);
 }
}

 /*
/*
 * Bitwise rotate a 32-bit number to the left.
 * Bitwise rotate a 32-bit number to the left.
 */
 */
 function bit_rol(num, cnt)
function bit_rol(num, cnt)
 {
{
 return (num << cnt) | (num >>> (32 - cnt));
  return (num << cnt) | (num >>> (32 - cnt));
 }
}

 /*
/*
 * Convert a string to an array of little-endian words
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
 */
 function str2binl(str)
function str2binl(str)
 {
{
 var bin = Array();
  var bin = Array();
 var mask = (1 << chrsz) - 1;
  var mask = (1 << chrsz) - 1;
 for(var i = 0; i < str.length * chrsz; i += chrsz)
  for(var i = 0; i < str.length * chrsz; i += chrsz)
 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
 return bin;
  return bin;
 }
}

 /*
/*
 * Convert an array of little-endian words to a string
 * Convert an array of little-endian words to a string
 */
 */
 function binl2str(bin)
function binl2str(bin)
 {
{
 var str = "";
  var str = "";
 var mask = (1 << chrsz) - 1;
  var mask = (1 << chrsz) - 1;
 for(var i = 0; i < bin.length * 32; i += chrsz)
  for(var i = 0; i < bin.length * 32; i += chrsz)
 str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
 return str;
  return str;
 }
}

 /*
/*
 * Convert an array of little-endian words to a hex string.
 * Convert an array of little-endian words to a hex string.
 */
 */
 function binl2hex(binarray)
function binl2hex(binarray)
 {
{
 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
 var str = "";
  var str = "";
 for(var i = 0; i < binarray.length * 4; i++)
  for(var i = 0; i < binarray.length * 4; i++)
 {
  {
 str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
 hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
 }
  }
 return str;
  return str;
 }
}

 String.prototype.trim = function(){return this.replace(/(^s*)|(s*$)/g, "");}
String.prototype.trim = function(){return this.replace(/(^s*)|(s*$)/g, "");}

 function md5(text) {
function md5(text) {
 return hex_md5(text.trim());
    return hex_md5(text.trim());
 }
}
MD5功能:
输入随意长度的信息,经过处理,输出为128位的信息(数字指纹);
不同的输入得到的不同的结果(唯一性);
依据128位的输出结果不可能反推出输入的信息(不可逆);
MD5属不属于加密算法:
觉得不属于的人是由于他们觉得不能从密文(散列值)反过来得到原文,即没有解密算法,所以这部分人觉得MD5仅仅能属于算法,不能称为加密算法;
觉得属于的人是由于他们觉得经过MD5处理后看不到原文,即已经将原文加密,所以觉得MD5属于加密算法;我个人支持后者。
MD5用途:
1、防止被篡改:
1)比方发送一个电子文档,发送前,我先得到MD5的输出结果a。然后在对方收到电子文档后,对方也得到一个MD5的输出结果b。假设a与b一样就代表中途未被篡改。2)比方我提供文件下载,为了防止不法分子在安装程序中加入木马,我能够在站点上发布由安装文件得到的MD5输出结果。3)SVN在检測文件是否在CheckOut后被改动过,也是用到了MD5.
2、防止直接看到明文:
如今非常多站点在数据库存储用户的password的时候都是存储用户password的MD5值。这样就算不法分子得到数据库的用户password的MD5值,也无法知道用户的password(事实上这样是不安全的,后面我会提到)。(比方在UNIX系统中用户的password就是以MD5(或其他类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的password计算成MD5值,然后再去和保存在文件系统中的MD5值进行比較,进而确定输入的password是否正确。通过这种步骤,系统在并不知道用户password的明码的情况下就能够确定用户登录系统的合法性。这不但能够避免用户的password被具有系统管理员权限的用户知道,并且还在一定程度上添加了password被破解的难度。)
3、防止抵赖(数字签名):
这须要一个第三方认证机构。比如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。若以后A说这文件不是他写的,权威机构仅仅需对此文件又一次产生摘要信息,然后跟记录在冊的摘要信息进行比对,同样的话,就证明是A写的了。这就是所谓的“数字签名”。
MD5算法过程:
对MD5算法简要的叙述能够为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
第一步、填充:假设输入信息的长度(bit)对512求余的结果不等于448,就须要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);
第二步、记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。
第三步、装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。假设在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有点晕哈,事实上想一想就明确了。
第四步、四轮循环运算:循环的次数是分组的个数(N+1)
1)将每一512字节细分成16个小组,每一个小组64位(8个字节)
2)先认识四个线性函数(&是与,|是或,~是非,^是异或)
  F(X,Y,Z)=(X&Y)|((~X)&Z)
G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=X^Y^Z
I(X,Y,Z)=Y^(X|(~Z))
    G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=X^Y^Z
I(X,Y,Z)=Y^(X|(~Z))
3)设Mj表示消息的第j个子分组(从0到15),<<<s表示循环左移s位,则四种操作为:
  FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s)
GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s)
HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s)
II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)
GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s)
HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s)
II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)
4)四轮运算
第一轮
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)
第二轮
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三轮
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)
第四轮
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)
第二轮
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三轮
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)
第四轮
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
5)每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环。
假设上面的过程用JAVA代码来实现的话,代码例如以下:
 package woxingwosu;
package woxingwosu;

 /************************************************
/************************************************ * MD5 算法
 * MD5 算法 * @author 我行我素
 * @author 我行我素 * @Date 2007-07-01
 * @Date 2007-07-01 *************************************************/
*************************************************/ public class MD5 {
public class MD5 {
 static final String hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
    static final String hexs[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"}; //标准的幻数
    //标准的幻数 private static final long A=0x67452301L;
    private static final long A=0x67452301L; private static final long B=0xefcdab89L;
    private static final long B=0xefcdab89L; private static final long C=0x98badcfeL;
    private static final long C=0x98badcfeL; private static final long D=0x10325476L;
    private static final long D=0x10325476L;
 
     //以下这些S11-S44实际上是一个4*4的矩阵,在四轮循环运算中用到
    //以下这些S11-S44实际上是一个4*4的矩阵,在四轮循环运算中用到 static final int S11 = 7;
    static final int S11 = 7; static final int S12 = 12;
    static final int S12 = 12; static final int S13 = 17;
    static final int S13 = 17; static final int S14 = 22;
    static final int S14 = 22;
 static final int S21 = 5;
    static final int S21 = 5; static final int S22 = 9;
    static final int S22 = 9; static final int S23 = 14;
    static final int S23 = 14; static final int S24 = 20;
    static final int S24 = 20;
 static final int S31 = 4;
    static final int S31 = 4; static final int S32 = 11;
    static final int S32 = 11; static final int S33 = 16;
    static final int S33 = 16; static final int S34 = 23;
    static final int S34 = 23;
 static final int S41 = 6;
    static final int S41 = 6; static final int S42 = 10;
    static final int S42 = 10; static final int S43 = 15;
    static final int S43 = 15; static final int S44 = 21;
    static final int S44 = 21; 
     //java不支持无符号的基本数据(unsigned)
    //java不支持无符号的基本数据(unsigned) private long [] result={A,B,C,D};//存储hash结果,共4×32=128位,初始化值为(幻数的级联)
    private long [] result={A,B,C,D};//存储hash结果,共4×32=128位,初始化值为(幻数的级联) 
     public static void main(String []args){
    public static void main(String []args){ MD5 md=new MD5();
        MD5 md=new MD5(); System.out.println("md5(abc)="+md.digest("abc"));
        System.out.println("md5(abc)="+md.digest("abc")); }
    } 
     private String digest(String inputStr){
    private String digest(String inputStr){ byte [] inputBytes=inputStr.getBytes();
        byte [] inputBytes=inputStr.getBytes(); int byteLen=inputBytes.length;//长度(字节)
        int byteLen=inputBytes.length;//长度(字节) int groupCount=0;//完整分组的个数
        int groupCount=0;//完整分组的个数 groupCount=byteLen/64;//每组512位(64字节)
        groupCount=byteLen/64;//每组512位(64字节) long []groups=null;//每一个小组(64字节)再细分后的16个小组(4字节)
        long []groups=null;//每一个小组(64字节)再细分后的16个小组(4字节) 
         //处理每个完整 分组
        //处理每个完整 分组 for(int step=0;step<groupCount;step++){
        for(int step=0;step<groupCount;step++){ groups=divGroup(inputBytes,step*64);
            groups=divGroup(inputBytes,step*64); trans(groups);//处理分组,核心算法
            trans(groups);//处理分组,核心算法 }
        } 
         //处理完整分组后的尾巴
        //处理完整分组后的尾巴 int rest=byteLen%64;//512位分组后的余数
        int rest=byteLen%64;//512位分组后的余数 byte [] tempBytes=new byte[64];
        byte [] tempBytes=new byte[64]; if(rest<=56){
        if(rest<=56){ for(int i=0;i<rest;i++)
            for(int i=0;i<rest;i++) tempBytes[i]=inputBytes[byteLen-rest+i];
                tempBytes[i]=inputBytes[byteLen-rest+i]; if(rest<56){
            if(rest<56){ tempBytes[rest]=(byte)(1<<7);
                tempBytes[rest]=(byte)(1<<7); for(int i=1;i<56-rest;i++)
                for(int i=1;i<56-rest;i++) tempBytes[rest+i]=0;
                    tempBytes[rest+i]=0; }
            } long len=(long)(byteLen<<3);
            long len=(long)(byteLen<<3); for(int i=0;i<8;i++){
            for(int i=0;i<8;i++){ tempBytes[56+i]=(byte)(len&0xFFL);
                tempBytes[56+i]=(byte)(len&0xFFL); len=len>>8;
                len=len>>8; }
            } groups=divGroup(tempBytes,0);
            groups=divGroup(tempBytes,0); trans(groups);//处理分组
            trans(groups);//处理分组 }else{
        }else{ for(int i=0;i<rest;i++)
            for(int i=0;i<rest;i++) tempBytes[i]=inputBytes[byteLen-rest+i];
                tempBytes[i]=inputBytes[byteLen-rest+i]; tempBytes[rest]=(byte)(1<<7);
            tempBytes[rest]=(byte)(1<<7); for(int i=rest+1;i<64;i++)
            for(int i=rest+1;i<64;i++) tempBytes[i]=0;
                tempBytes[i]=0; groups=divGroup(tempBytes,0);
            groups=divGroup(tempBytes,0); trans(groups);//处理分组
            trans(groups);//处理分组 
             for(int i=0;i<56;i++)
            for(int i=0;i<56;i++) tempBytes[i]=0;
                tempBytes[i]=0; long len=(long)(byteLen<<3);
            long len=(long)(byteLen<<3); for(int i=0;i<8;i++){
            for(int i=0;i<8;i++){ tempBytes[56+i]=(byte)(len&0xFFL);
                tempBytes[56+i]=(byte)(len&0xFFL); len=len>>8;
                len=len>>8; }
            } groups=divGroup(tempBytes,0);
            groups=divGroup(tempBytes,0); trans(groups);//处理分组
            trans(groups);//处理分组 }
        } 
         //将Hash值转换成十六进制的字符串
        //将Hash值转换成十六进制的字符串 String resStr="";
        String resStr=""; long temp=0;
        long temp=0; for(int i=0;i<4;i++){
        for(int i=0;i<4;i++){ for(int j=0;j<4;j++){
            for(int j=0;j<4;j++){ temp=result[i]&0x0FL;
                temp=result[i]&0x0FL; String a=hexs[(int)(temp)];
                String a=hexs[(int)(temp)]; result[i]=result[i]>>4;
                result[i]=result[i]>>4; temp=result[i]&0x0FL;
                temp=result[i]&0x0FL; resStr+=hexs[(int)(temp)]+a;
                resStr+=hexs[(int)(temp)]+a; result[i]=result[i]>>4;
                result[i]=result[i]>>4; }
            } }
        } return resStr;
        return resStr; }
    } 
     /**
    /** * 从inputBytes的index開始取512位,作为新的分组
     * 从inputBytes的index開始取512位,作为新的分组 * 将每个512位的分组再细分成16个小组,每个小组64位(8个字节)
     * 将每个512位的分组再细分成16个小组,每个小组64位(8个字节) * @param inputBytes
     * @param inputBytes * @param index
     * @param index * @return
     * @return */
     */ private static long[] divGroup(byte[] inputBytes,int index){
    private static long[] divGroup(byte[] inputBytes,int index){ long [] temp=new long[16];
        long [] temp=new long[16]; for(int i=0;i<16;i++){
        for(int i=0;i<16;i++){ temp[i]=b2iu(inputBytes[4*i+index])|
            temp[i]=b2iu(inputBytes[4*i+index])| (b2iu(inputBytes[4*i+1+index]))<<8|
                (b2iu(inputBytes[4*i+1+index]))<<8| (b2iu(inputBytes[4*i+2+index]))<<16|
                (b2iu(inputBytes[4*i+2+index]))<<16| (b2iu(inputBytes[4*i+3+index]))<<24;
                (b2iu(inputBytes[4*i+3+index]))<<24; }
        } return temp;
        return temp; }
    } 
     /**
    /** * 这时不存在符号位(符号位存储不再是代表正负),所以须要处理一下
     * 这时不存在符号位(符号位存储不再是代表正负),所以须要处理一下 * @param b
     * @param b * @return
     * @return */
     */ public static long b2iu(byte b){
    public static long b2iu(byte b){ return b < 0 ? b & 0x7F + 128 : b;
        return b < 0 ? b & 0x7F + 128 : b; }
     } 
     /**
    /** * 基本的操作,四轮循环
     * 基本的操作,四轮循环 * @param groups[]--每个分组512位(64字节)
     * @param groups[]--每个分组512位(64字节) */
     */ private void trans(long[] groups) {
    private void trans(long[] groups) { long a = result[0], b = result[1], c = result[2], d = result[3];
        long a = result[0], b = result[1], c = result[2], d = result[3]; /*第一轮*/
        /*第一轮*/ a = FF(a, b, c, d, groups[0], S11, 0xd76aa478L); /* 1 */
        a = FF(a, b, c, d, groups[0], S11, 0xd76aa478L); /* 1 */ d = FF(d, a, b, c, groups[1], S12, 0xe8c7b756L); /* 2 */
        d = FF(d, a, b, c, groups[1], S12, 0xe8c7b756L); /* 2 */ c = FF(c, d, a, b, groups[2], S13, 0x242070dbL); /* 3 */
        c = FF(c, d, a, b, groups[2], S13, 0x242070dbL); /* 3 */ b = FF(b, c, d, a, groups[3], S14, 0xc1bdceeeL); /* 4 */
        b = FF(b, c, d, a, groups[3], S14, 0xc1bdceeeL); /* 4 */ a = FF(a, b, c, d, groups[4], S11, 0xf57c0fafL); /* 5 */
        a = FF(a, b, c, d, groups[4], S11, 0xf57c0fafL); /* 5 */ d = FF(d, a, b, c, groups[5], S12, 0x4787c62aL); /* 6 */
        d = FF(d, a, b, c, groups[5], S12, 0x4787c62aL); /* 6 */ c = FF(c, d, a, b, groups[6], S13, 0xa8304613L); /* 7 */
        c = FF(c, d, a, b, groups[6], S13, 0xa8304613L); /* 7 */ b = FF(b, c, d, a, groups[7], S14, 0xfd469501L); /* 8 */
        b = FF(b, c, d, a, groups[7], S14, 0xfd469501L); /* 8 */ a = FF(a, b, c, d, groups[8], S11, 0x698098d8L); /* 9 */
        a = FF(a, b, c, d, groups[8], S11, 0x698098d8L); /* 9 */ d = FF(d, a, b, c, groups[9], S12, 0x8b44f7afL); /* 10 */
        d = FF(d, a, b, c, groups[9], S12, 0x8b44f7afL); /* 10 */ c = FF(c, d, a, b, groups[10], S13, 0xffff5bb1L); /* 11 */
        c = FF(c, d, a, b, groups[10], S13, 0xffff5bb1L); /* 11 */ b = FF(b, c, d, a, groups[11], S14, 0x895cd7beL); /* 12 */
        b = FF(b, c, d, a, groups[11], S14, 0x895cd7beL); /* 12 */ a = FF(a, b, c, d, groups[12], S11, 0x6b901122L); /* 13 */
        a = FF(a, b, c, d, groups[12], S11, 0x6b901122L); /* 13 */ d = FF(d, a, b, c, groups[13], S12, 0xfd987193L); /* 14 */
        d = FF(d, a, b, c, groups[13], S12, 0xfd987193L); /* 14 */ c = FF(c, d, a, b, groups[14], S13, 0xa679438eL); /* 15 */
        c = FF(c, d, a, b, groups[14], S13, 0xa679438eL); /* 15 */ b = FF(b, c, d, a, groups[15], S14, 0x49b40821L); /* 16 */
        b = FF(b, c, d, a, groups[15], S14, 0x49b40821L); /* 16 */
 /*第二轮*/
        /*第二轮*/ a = GG(a, b, c, d, groups[1], S21, 0xf61e2562L); /* 17 */
        a = GG(a, b, c, d, groups[1], S21, 0xf61e2562L); /* 17 */ d = GG(d, a, b, c, groups[6], S22, 0xc040b340L); /* 18 */
        d = GG(d, a, b, c, groups[6], S22, 0xc040b340L); /* 18 */ c = GG(c, d, a, b, groups[11], S23, 0x265e5a51L); /* 19 */
        c = GG(c, d, a, b, groups[11], S23, 0x265e5a51L); /* 19 */ b = GG(b, c, d, a, groups[0], S24, 0xe9b6c7aaL); /* 20 */
        b = GG(b, c, d, a, groups[0], S24, 0xe9b6c7aaL); /* 20 */ a = GG(a, b, c, d, groups[5], S21, 0xd62f105dL); /* 21 */
        a = GG(a, b, c, d, groups[5], S21, 0xd62f105dL); /* 21 */ d = GG(d, a, b, c, groups[10], S22, 0x2441453L); /* 22 */
        d = GG(d, a, b, c, groups[10], S22, 0x2441453L); /* 22 */ c = GG(c, d, a, b, groups[15], S23, 0xd8a1e681L); /* 23 */
        c = GG(c, d, a, b, groups[15], S23, 0xd8a1e681L); /* 23 */ b = GG(b, c, d, a, groups[4], S24, 0xe7d3fbc8L); /* 24 */
        b = GG(b, c, d, a, groups[4], S24, 0xe7d3fbc8L); /* 24 */ a = GG(a, b, c, d, groups[9], S21, 0x21e1cde6L); /* 25 */
        a = GG(a, b, c, d, groups[9], S21, 0x21e1cde6L); /* 25 */ d = GG(d, a, b, c, groups[14], S22, 0xc33707d6L); /* 26 */
        d = GG(d, a, b, c, groups[14], S22, 0xc33707d6L); /* 26 */ c = GG(c, d, a, b, groups[3], S23, 0xf4d50d87L); /* 27 */
        c = GG(c, d, a, b, groups[3], S23, 0xf4d50d87L); /* 27 */ b = GG(b, c, d, a, groups[8], S24, 0x455a14edL); /* 28 */
        b = GG(b, c, d, a, groups[8], S24, 0x455a14edL); /* 28 */ a = GG(a, b, c, d, groups[13], S21, 0xa9e3e905L); /* 29 */
        a = GG(a, b, c, d, groups[13], S21, 0xa9e3e905L); /* 29 */ d = GG(d, a, b, c, groups[2], S22, 0xfcefa3f8L); /* 30 */
        d = GG(d, a, b, c, groups[2], S22, 0xfcefa3f8L); /* 30 */ c = GG(c, d, a, b, groups[7], S23, 0x676f02d9L); /* 31 */
        c = GG(c, d, a, b, groups[7], S23, 0x676f02d9L); /* 31 */ b = GG(b, c, d, a, groups[12], S24, 0x8d2a4c8aL); /* 32 */
        b = GG(b, c, d, a, groups[12], S24, 0x8d2a4c8aL); /* 32 */
 /*第三轮*/
        /*第三轮*/ a = HH(a, b, c, d, groups[5], S31, 0xfffa3942L); /* 33 */
        a = HH(a, b, c, d, groups[5], S31, 0xfffa3942L); /* 33 */ d = HH(d, a, b, c, groups[8], S32, 0x8771f681L); /* 34 */
        d = HH(d, a, b, c, groups[8], S32, 0x8771f681L); /* 34 */ c = HH(c, d, a, b, groups[11], S33, 0x6d9d6122L); /* 35 */
        c = HH(c, d, a, b, groups[11], S33, 0x6d9d6122L); /* 35 */ b = HH(b, c, d, a, groups[14], S34, 0xfde5380cL); /* 36 */
        b = HH(b, c, d, a, groups[14], S34, 0xfde5380cL); /* 36 */ a = HH(a, b, c, d, groups[1], S31, 0xa4beea44L); /* 37 */
        a = HH(a, b, c, d, groups[1], S31, 0xa4beea44L); /* 37 */ d = HH(d, a, b, c, groups[4], S32, 0x4bdecfa9L); /* 38 */
        d = HH(d, a, b, c, groups[4], S32, 0x4bdecfa9L); /* 38 */ c = HH(c, d, a, b, groups[7], S33, 0xf6bb4b60L); /* 39 */
        c = HH(c, d, a, b, groups[7], S33, 0xf6bb4b60L); /* 39 */ b = HH(b, c, d, a, groups[10], S34, 0xbebfbc70L); /* 40 */
        b = HH(b, c, d, a, groups[10], S34, 0xbebfbc70L); /* 40 */ a = HH(a, b, c, d, groups[13], S31, 0x289b7ec6L); /* 41 */
        a = HH(a, b, c, d, groups[13], S31, 0x289b7ec6L); /* 41 */ d = HH(d, a, b, c, groups[0], S32, 0xeaa127faL); /* 42 */
        d = HH(d, a, b, c, groups[0], S32, 0xeaa127faL); /* 42 */ c = HH(c, d, a, b, groups[3], S33, 0xd4ef3085L); /* 43 */
        c = HH(c, d, a, b, groups[3], S33, 0xd4ef3085L); /* 43 */ b = HH(b, c, d, a, groups[6], S34, 0x4881d05L); /* 44 */
        b = HH(b, c, d, a, groups[6], S34, 0x4881d05L); /* 44 */ a = HH(a, b, c, d, groups[9], S31, 0xd9d4d039L); /* 45 */
        a = HH(a, b, c, d, groups[9], S31, 0xd9d4d039L); /* 45 */ d = HH(d, a, b, c, groups[12], S32, 0xe6db99e5L); /* 46 */
        d = HH(d, a, b, c, groups[12], S32, 0xe6db99e5L); /* 46 */ c = HH(c, d, a, b, groups[15], S33, 0x1fa27cf8L); /* 47 */
        c = HH(c, d, a, b, groups[15], S33, 0x1fa27cf8L); /* 47 */ b = HH(b, c, d, a, groups[2], S34, 0xc4ac5665L); /* 48 */
        b = HH(b, c, d, a, groups[2], S34, 0xc4ac5665L); /* 48 */
 /*第四轮*/
        /*第四轮*/ a = II(a, b, c, d, groups[0], S41, 0xf4292244L); /* 49 */
        a = II(a, b, c, d, groups[0], S41, 0xf4292244L); /* 49 */ d = II(d, a, b, c, groups[7], S42, 0x432aff97L); /* 50 */
        d = II(d, a, b, c, groups[7], S42, 0x432aff97L); /* 50 */ c = II(c, d, a, b, groups[14], S43, 0xab9423a7L); /* 51 */
        c = II(c, d, a, b, groups[14], S43, 0xab9423a7L); /* 51 */ b = II(b, c, d, a, groups[5], S44, 0xfc93a039L); /* 52 */
        b = II(b, c, d, a, groups[5], S44, 0xfc93a039L); /* 52 */ a = II(a, b, c, d, groups[12], S41, 0x655b59c3L); /* 53 */
        a = II(a, b, c, d, groups[12], S41, 0x655b59c3L); /* 53 */ d = II(d, a, b, c, groups[3], S42, 0x8f0ccc92L); /* 54 */
        d = II(d, a, b, c, groups[3], S42, 0x8f0ccc92L); /* 54 */ c = II(c, d, a, b, groups[10], S43, 0xffeff47dL); /* 55 */
        c = II(c, d, a, b, groups[10], S43, 0xffeff47dL); /* 55 */ b = II(b, c, d, a, groups[1], S44, 0x85845dd1L); /* 56 */
        b = II(b, c, d, a, groups[1], S44, 0x85845dd1L); /* 56 */ a = II(a, b, c, d, groups[8], S41, 0x6fa87e4fL); /* 57 */
        a = II(a, b, c, d, groups[8], S41, 0x6fa87e4fL); /* 57 */ d = II(d, a, b, c, groups[15], S42, 0xfe2ce6e0L); /* 58 */
        d = II(d, a, b, c, groups[15], S42, 0xfe2ce6e0L); /* 58 */ c = II(c, d, a, b, groups[6], S43, 0xa3014314L); /* 59 */
        c = II(c, d, a, b, groups[6], S43, 0xa3014314L); /* 59 */ b = II(b, c, d, a, groups[13], S44, 0x4e0811a1L); /* 60 */
        b = II(b, c, d, a, groups[13], S44, 0x4e0811a1L); /* 60 */ a = II(a, b, c, d, groups[4], S41, 0xf7537e82L); /* 61 */
        a = II(a, b, c, d, groups[4], S41, 0xf7537e82L); /* 61 */ d = II(d, a, b, c, groups[11], S42, 0xbd3af235L); /* 62 */
        d = II(d, a, b, c, groups[11], S42, 0xbd3af235L); /* 62 */ c = II(c, d, a, b, groups[2], S43, 0x2ad7d2bbL); /* 63 */
        c = II(c, d, a, b, groups[2], S43, 0x2ad7d2bbL); /* 63 */ b = II(b, c, d, a, groups[9], S44, 0xeb86d391L); /* 64 */
        b = II(b, c, d, a, groups[9], S44, 0xeb86d391L); /* 64 */
 /*增加到之前计算的结果其中*/
        /*增加到之前计算的结果其中*/ result[0] += a;
        result[0] += a; result[1] += b;
        result[1] += b; result[2] += c;
        result[2] += c; result[3] += d;
        result[3] += d; result[0]=result[0]&0xFFFFFFFFL;
        result[0]=result[0]&0xFFFFFFFFL; result[1]=result[1]&0xFFFFFFFFL;
        result[1]=result[1]&0xFFFFFFFFL; result[2]=result[2]&0xFFFFFFFFL;
        result[2]=result[2]&0xFFFFFFFFL; result[3]=result[3]&0xFFFFFFFFL;
        result[3]=result[3]&0xFFFFFFFFL; }
    } 
     /**
    /** * 以下是处理要用到的线性函数
     * 以下是处理要用到的线性函数 */
     */ private static long F(long x, long y, long z) {
    private static long F(long x, long y, long z) { return (x & y) | ((~x) & z);
        return (x & y) | ((~x) & z); }
    }
 private static long G(long x, long y, long z) {
    private static long G(long x, long y, long z) { return (x & z) | (y & (~z));
        return (x & z) | (y & (~z)); }
    }
 private static long H(long x, long y, long z) {
    private static long H(long x, long y, long z) { return x ^ y ^ z;
        return x ^ y ^ z; }
    }
 private static long I(long x, long y, long z) {
    private static long I(long x, long y, long z) { return y ^ (x | (~z));
        return y ^ (x | (~z)); }
    }
 private static long FF(long a, long b, long c, long d, long x, long s,
    private static long FF(long a, long b, long c, long d, long x, long s, long ac) {
            long ac) { a += (F(b, c, d)&0xFFFFFFFFL) + x + ac;
        a += (F(b, c, d)&0xFFFFFFFFL) + x + ac; a = ((a&0xFFFFFFFFL)<< s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a = ((a&0xFFFFFFFFL)<< s) | ((a&0xFFFFFFFFL) >>> (32 - s)); a += b;
        a += b; return (a&0xFFFFFFFFL);
        return (a&0xFFFFFFFFL); }
    }
 private static long GG(long a, long b, long c, long d, long x, long s,
    private static long GG(long a, long b, long c, long d, long x, long s, long ac) {
            long ac) { a += (G(b, c, d)&0xFFFFFFFFL) + x + ac;
        a += (G(b, c, d)&0xFFFFFFFFL) + x + ac; a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s)); a += b;
        a += b; return (a&0xFFFFFFFFL);
        return (a&0xFFFFFFFFL); }
    }
 private static long HH(long a, long b, long c, long d, long x, long s,
    private static long HH(long a, long b, long c, long d, long x, long s, long ac) {
            long ac) { a += (H(b, c, d)&0xFFFFFFFFL) + x + ac;
        a += (H(b, c, d)&0xFFFFFFFFL) + x + ac; a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s)); a += b;
        a += b; return (a&0xFFFFFFFFL);
        return (a&0xFFFFFFFFL); }
    }
 private static long II(long a, long b, long c, long d, long x, long s,
    private static long II(long a, long b, long c, long d, long x, long s, long ac) {
            long ac) { a += (I(b, c, d)&0xFFFFFFFFL) + x + ac;
        a += (I(b, c, d)&0xFFFFFFFFL) + x + ac; a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s));
        a = ((a&0xFFFFFFFFL) << s) | ((a&0xFFFFFFFFL) >>> (32 - s)); a += b;
        a += b; return (a&0xFFFFFFFFL);
        return (a&0xFFFFFFFFL); }
    } }
}
普遍觉得MD5是非常安全,由于暴力破解的时间是一般人无法接受的。实际上假设把用户的passwordMD5处理后再存储到数据库,事实上是非常不安全的。由于用户的password是比較短的,并且非常多用户的password都使用生日,手机号码,身份证号码,电话号码等等。或者使用经常使用的一些吉利的数字,或者某个英文单词。假设我把经常使用的password先MD5处理,把数据存储起来,然后再跟你的MD5结果匹配,这时我就有可能得到明文。比方某个MD5破解站点http://www.cmd5.com/default.aspx,我把其站点下的公告复制例如以下
  md5破解、动网论坛password破解等不再须要用穷举法,本站共同拥有md5记录235亿条,还在不断增长中,已包括10位及10位下面数字、7位字母、部分7位字母+数字,所有6位及下面字母加数字等组合,并针对国内用户做了大量优化,比如已经包括所有手机号码、全国部分大中城市固定电话号码、百家姓、经常使用拼音等大量组合,另增加了某大型站点真实会员password数据10万条。本站数据量大,查询速度快,同一时候支持16位及32位password查询。通过对10万会员的真实动网论坛样本数据的測试,本站对于动网论坛password的命中率达到83%。
本站4T的硬盘已经上线,正在生成数据,估计须要2个月左右时间,到时候本站能查询到12位数字和9位字母。
   你能够用你的生日,手机号码去測试一下。本站4T的硬盘已经上线,正在生成数据,估计须要2个月左右时间,到时候本站能查询到12位数字和9位字母。
我认为仅仅须要将上面我写的MD5的标准幻数A,B,C,D的值改动一下,改动后也不是MD5算法了,由于不能保证唯一性。这样就算别人得到32位的值,他假设不知道幻数的值是无法还原明文的。就算得到了幻数,也是非常难破解的。
JAVA实现MD5
在java中实现MD5是非常easy的,在包java.security有个类MessageDigest。官方文档例如以下
    MessageDigest 类为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。信息摘要是安全的单向哈希函数,它接收随意大小的数据,输出固定长度的哈希值。 
MessageDigest 对象開始被初始化。该对象通过使用 update 方法处理数据。不论什么时候都能够调用 reset 方法重置摘要。一旦全部须要更新的数据都已经被更新了,应该调用 digest 方法之中的一个完毕哈希计算。
对于给定数量的更新数据,digest 方法仅仅能被调用一次。digest 被调用后,MessageDigest 对象被又一次设置成其初始状态。
   使用MessageDigest非常easy,比如 
MessageDigest 对象開始被初始化。该对象通过使用 update 方法处理数据。不论什么时候都能够调用 reset 方法重置摘要。一旦全部须要更新的数据都已经被更新了,应该调用 digest 方法之中的一个完毕哈希计算。
对于给定数量的更新数据,digest 方法仅仅能被调用一次。digest 被调用后,MessageDigest 对象被又一次设置成其初始状态。
 package woxingwosu;
package woxingwosu; /************************************************
/************************************************ * MD5 算法
 * MD5 算法 * @author 我行我素
 * @author 我行我素 * @Date 2007-07-06
 * @Date 2007-07-06 *************************************************/
*************************************************/ import java.security.MessageDigest;
import java.security.MessageDigest;
 public class MyMD5 {
public class MyMD5 {
 static char[] hex = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    static char[] hex = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};  public static void main(String[] args) {
    public static void main(String[] args) { try{
        try{ MessageDigest md5 = MessageDigest.getInstance("MD5");//申明使用MD5算法
            MessageDigest md5 = MessageDigest.getInstance("MD5");//申明使用MD5算法 md5.update("a".getBytes());//
            md5.update("a".getBytes());// System.out.println("md5(a)="+byte2str(md5.digest()));
            System.out.println("md5(a)="+byte2str(md5.digest())); md5.update("a".getBytes());
            md5.update("a".getBytes()); md5.update("bc".getBytes());
            md5.update("bc".getBytes()); System.out.println("md5(abc)="+byte2str(md5.digest()));
            System.out.println("md5(abc)="+byte2str(md5.digest())); }catch(Exception e){
        }catch(Exception e){ e.printStackTrace();
            e.printStackTrace(); }
        } }
    } 
     /**
    /** * 将字节数组转换成十六进制字符串
     * 将字节数组转换成十六进制字符串 * @param bytes
     * @param bytes * @return
     * @return */
     */ private static String byte2str(byte []bytes){
    private static String byte2str(byte []bytes){ int len = bytes.length;
        int len = bytes.length;    StringBuffer result = new StringBuffer();
        StringBuffer result = new StringBuffer();     for (int i = 0; i < len; i++) {
        for (int i = 0; i < len; i++) {    byte byte0 = bytes[i];
            byte byte0 = bytes[i];    result.append(hex[byte0 >>> 4 & 0xf]);
            result.append(hex[byte0 >>> 4 & 0xf]);    result.append(hex[byte0 & 0xf]);
            result.append(hex[byte0 & 0xf]);    }
        } return result.toString();
        return result.toString(); }
    } }
} 
1)JS版的MD5(调用方法:md5(明文))
 /*
/* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321.
 * Digest Algorithm, as defined in RFC 1321. * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License
 * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info.
 * See http://pajhome.org.uk/crypt/md5 for more info. */
 */
 /*
/* * Configurable variables. You may need to tweak these to be compatible with
 * Configurable variables. You may need to tweak these to be compatible with * the server-side, but the defaults work in most cases.
 * the server-side, but the defaults work in most cases. */
 */ var hexcase = 1;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var hexcase = 1;  /* hex output format. 0 - lowercase; 1 - uppercase        */ var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */ var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
 /*
/* * These are the functions you'll usually want to call
 * These are the functions you'll usually want to call * They take string arguments and return either hex or base-64 encoded strings
 * They take string arguments and return either hex or base-64 encoded strings */
 */ function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
 /*
/* * Calculate the MD5 of an array of little-endian words, and a bit length
 * Calculate the MD5 of an array of little-endian words, and a bit length */
 */ function core_md5(x, len)
function core_md5(x, len) {
{ /* append padding */
  /* append padding */ x[len >> 5] |= 0x80 << ((len) % 32);
  x[len >> 5] |= 0x80 << ((len) % 32); x[(((len + 64) >>> 9) << 4) + 14] = len;
  x[(((len + 64) >>> 9) << 4) + 14] = len;
 var a =  1732584193;
  var a =  1732584193; var b = -271733879;
  var b = -271733879; var c = -1732584194;
  var c = -1732584194; var d =  271733878;
  var d =  271733878;
 for(var i = 0; i < x.length; i += 16)
  for(var i = 0; i < x.length; i += 16) {
  { var olda = a;
    var olda = a; var oldb = b;
    var oldb = b; var oldc = c;
    var oldc = c; var oldd = d;
    var oldd = d;
 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819); b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426); c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416); d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063); b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682); d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713); b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083); c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438); d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501); a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473); b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562); b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353); c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174); d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189); a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520); b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415); c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571); d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359); d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649); a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259); b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
 a = safe_add(a, olda);
    a = safe_add(a, olda); b = safe_add(b, oldb);
    b = safe_add(b, oldb); c = safe_add(c, oldc);
    c = safe_add(c, oldc); d = safe_add(d, oldd);
    d = safe_add(d, oldd); }
  } return Array(a, b, c, d);
  return Array(a, b, c, d);
 }
}
 /*
/* * These functions implement the four basic operations the algorithm uses.
 * These functions implement the four basic operations the algorithm uses. */
 */ function md5_cmn(q, a, b, x, s, t)
function md5_cmn(q, a, b, x, s, t) {
{ return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); }
} function md5_ff(a, b, c, d, x, s, t)
function md5_ff(a, b, c, d, x, s, t) {
{ return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); }
} function md5_gg(a, b, c, d, x, s, t)
function md5_gg(a, b, c, d, x, s, t) {
{ return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); }
} function md5_hh(a, b, c, d, x, s, t)
function md5_hh(a, b, c, d, x, s, t) {
{ return md5_cmn(b ^ c ^ d, a, b, x, s, t);
  return md5_cmn(b ^ c ^ d, a, b, x, s, t); }
} function md5_ii(a, b, c, d, x, s, t)
function md5_ii(a, b, c, d, x, s, t) {
{ return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); }
}
 /*
/* * Calculate the HMAC-MD5, of a key and some data
 * Calculate the HMAC-MD5, of a key and some data */
 */ function core_hmac_md5(key, data)
function core_hmac_md5(key, data) {
{ var bkey = str2binl(key);
  var bkey = str2binl(key); if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
 var ipad = Array(16), opad = Array(16);
  var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++)
  for(var i = 0; i < 16; i++) {
  { ipad[i] = bkey[i] ^ 0x36363636;
    ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C;
    opad[i] = bkey[i] ^ 0x5C5C5C5C; }
  }
 var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); return core_md5(opad.concat(hash), 512 + 128);
  return core_md5(opad.concat(hash), 512 + 128); }
}
 /*
/* * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters.
 * to work around bugs in some JS interpreters. */
 */ function safe_add(x, y)
function safe_add(x, y) {
{ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF);
  return (msw << 16) | (lsw & 0xFFFF); }
}
 /*
/* * Bitwise rotate a 32-bit number to the left.
 * Bitwise rotate a 32-bit number to the left. */
 */ function bit_rol(num, cnt)
function bit_rol(num, cnt) {
{ return (num << cnt) | (num >>> (32 - cnt));
  return (num << cnt) | (num >>> (32 - cnt)); }
}
 /*
/* * Convert a string to an array of little-endian words
 * Convert a string to an array of little-endian words * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. */
 */ function str2binl(str)
function str2binl(str) {
{ var bin = Array();
  var bin = Array(); var mask = (1 << chrsz) - 1;
  var mask = (1 << chrsz) - 1; for(var i = 0; i < str.length * chrsz; i += chrsz)
  for(var i = 0; i < str.length * chrsz; i += chrsz) bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); return bin;
  return bin; }
}
 /*
/* * Convert an array of little-endian words to a string
 * Convert an array of little-endian words to a string */
 */ function binl2str(bin)
function binl2str(bin) {
{ var str = "";
  var str = ""; var mask = (1 << chrsz) - 1;
  var mask = (1 << chrsz) - 1; for(var i = 0; i < bin.length * 32; i += chrsz)
  for(var i = 0; i < bin.length * 32; i += chrsz) str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); return str;
  return str; }
}
 /*
/* * Convert an array of little-endian words to a hex string.
 * Convert an array of little-endian words to a hex string. */
 */ function binl2hex(binarray)
function binl2hex(binarray) {
{ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = "";
  var str = ""; for(var i = 0; i < binarray.length * 4; i++)
  for(var i = 0; i < binarray.length * 4; i++) {
  { str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF); }
  } return str;
  return str; }
}
 String.prototype.trim = function(){return this.replace(/(^s*)|(s*$)/g, "");}
String.prototype.trim = function(){return this.replace(/(^s*)|(s*$)/g, "");}
 function md5(text) {
function md5(text) { return hex_md5(text.trim());
    return hex_md5(text.trim()); }
} 
                    
                     
                    
                 
                    
                 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号