MD5加密

来源:互联网 发布:网络人远程控制 编辑:程序博客网 时间:2024/06/05 00:55

Md5加密原理

MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

在MD5算法中,首先需要对信息进行填充,使其字节长度对512求余数的结果等于448。因此,信息的字节长度(Bits Length)将被扩展至N*512+448,即N*64+56个字节(Bytes),N为一个正整数。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后再在这个结果后面附加一个以64位二进制表示的填充前的信息长度。经过这两步的处理,现在的信息字节长度=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍数。这样做的原因是为满足后面处理中对信息长度的要求。MD5中有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x01234567,B=0x89abcdef,C=0xfedcba98,D=0x76543210。 当设置好这四个链接变量后,就开始进入算法的四轮循环运算,循环的次数是信息中512位信息分组的数目。

将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。 主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量(文本中的一个子分组和一个常数)。

再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。 以一下是每次操作中用到的四个非线性函数(每轮一个)。

F(X,Y,Z)=(X∧Y)∨(( X)∧Z)G(X,Y,Z)=(X∧Z)∨(Y∧( Z))H(X,Y,Z)=X?Y?ZI(X,Y,Z)=Y?(X∨( Z))

其中,?是异或,∧是与,∨是或, 是反符号。

如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。F是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。所有这些完成之后,将A,B,C,D分别加上a,b,c,d。然后用下一分组数据继续运行算法,最后的输出是A,B,C和D的级联。最后得到的A,B,C,D就是输出结果,A是低位,D为高位,DCBA组成128位输出结果。

2.2 MD5的安全性

从安全的角度讲,MD5的输出为128位,若采用纯强力攻击寻找一个消息具有给定Hash值的计算困难性为2128,用每秒可试验1000000000个消息的计算机需时1.07×1022年。若采用生日攻击法,寻找有相同Hash值的两个消息需要试验264个消息,用每秒可试验1000000000个消息的计算机需时585年。

2.3 Md5加密算法的应用

MD5加密算法由于其具有较好的安全性,加之商业也可以免费使用该算法,因此该加密算法被广泛使用,md5算法主要运用在数字签名、文件完整性验证以及口令加密等方面。

3.改进后的加密方法

3.1目前md5加密方法利用的缺陷

在目前的信息系统中,对md5加密方法的利用主要通过在脚本页面中引用包含md5加密函数代码的文件,以asp脚本为例,在需要调用的页面中加入,md5.asp为md5加密函数代码文件,然后直接调用函数MD5(sMessage)即可,md5加密后的值有16位和32位之分,如果在md5加密函数中使用的是MD5 = LCase(WordToHex(a) & WordToHex(b) & WordToHex(c) & WordToHex(d)),则表示是32位,如果使用的是MD5=LCase(WordToHex(b) & WordToHex(c)),则表示是16位。例如对明文为“123456”的值进行加密,其md5值有两个,如下所示:

A=123456 password=md5(A)= 49ba59abbe56e057 password=md5(A)= e10adc3949ba59abbe56e057f20f883e 如果将加密的md5值直接保存在数据库,当网站存在注入或者其它漏洞时,入侵者极有可能获取用户的密码值,通过md5在


 

   

A=“123456”password=md5(A)= 49ba59abbe56e057 password=md5(A)= e10adc3949ba59abbe56e057f20f883e

如果将加密的md5值直接保存在数据库,当网站存在注入或者其它漏洞时,入侵者极有可能获取用户的密码值,通过md5在线查询或者暴力破解可以得到密码。

  MD5加密工具类

package day18;


import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public class MD5Object {
private static MessageDigest md = null;
    private static MessageDigest sha = null;
    private static long jishu[] = new long[8];
    static {
        try {
            md = MessageDigest.getInstance("MD5");
            sha = MessageDigest.getInstance("SHA-1");
            jishu[0] = 1;
            for ( int i = 1; i < 8; i++) {
                jishu[i] = jishu[i-1]*256;
            }    
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }




    }


    public String SHASum(String input) {
        if (sha == null || input == null) {
            return null;
        }
        sha.reset();
        sha.update(input.getBytes());
        byte[] sign = sha.digest();


        return bytes2Hex(sign);
    }


    public static String MD5Sum(String input) {
        if ( md == null ) {
            return null;
        }
        if ( input == null) {
            return null;
        }


        md.reset();
        md.update(input.getBytes());
        byte[] sign = md.digest();


        return bytes2Hex(sign);
    }    




    public Long MD5To64Bit(String input) {
        if ( md == null ) {
            return null;
        }
        if ( input == null) {
            return null;
        }


        md.reset();
        md.update(input.getBytes());
        byte[] sign = md.digest();
        long fst = transfer64bitsTolong(sign, 0);
        long second = transfer64bitsTolong(sign, 8);


        return Long.valueOf(fst + second);
    }


    private long transfer64bitsTolong(byte[] input, int start) {
        long result = 0;


        if (start + 8 <= input.length) {
            int tmp = 0;
            for ( int i = 0; i < 7 ; i++ ) {
                tmp = Byte.valueOf(input[start + i]).intValue();
                if ( tmp < 0) {
                    tmp = tmp & 0x7f + 0x80;
                }    
                result = result + tmp*jishu[i];
            }
            int last = Byte.valueOf(input[start + 7]).intValue();
            if ( last < 0 ) {
                last = last & 0x7f;
                result = last * jishu[7] + result;
                result = Long.MIN_VALUE + result;
            } else {
                result = last * jishu[7] + result; 
            }
        }


        return result;
    }    


    /**
     * 将字节数组转换成16进制的字符串
     * @param bts
     * @return
     */
    private static String bytes2Hex(byte[] bts) {
        String des = "";
        String tmp = null;


        for (int i = 0; i < bts.length; i++) {
            tmp = (Integer.toHexString(bts[i] & 0xFF));
            if (tmp.length() == 1) {
                des += "0";
            }
            des += tmp;
        }
        return des;
    }


    public static void main(String[] args) {
        MD5Object md5 = new MD5Object();
        System.out.println(md5.MD5Sum("zpf1993"));
    }


}





0 0