md5 实现原理

第一段主题:md5 是什么,有神马用?

第一段内容:message-digest algorithm 5 (信息-摘要算法)是一种将字符串经过一系列计算处理以后,得到一个32位的16进制串比如(ADAF1231A1B4AF12ADAF1231A1B4AF12)  。     有什么用呢?我用过的一种是在a程序中给参数加密,通过网络调用,参数传递到了b程序,如何保证参数再传递过程中没有被别的程序篡改,从而使用到了md5 给参数加密。 当然还有一种使用较多的情景是文件的下载。服务器上的文件先通过将自己的内容加密,得到md5串,用户下载了文件之后,再次将文件内容加密成md5 ,比较两者是否一致,如果不一致,则认为文件内容被改动了。


第二段:java如果获得任意一个字符串的md5值?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class MD5Test {
 
     //main测试类
     public static void main(String[] args) {
         String result = getMD5( "aaa" );
         System.err.println(result);
     }
 
     /**
      * 生成md5
      * @param message
      * @return
      */
     public static String getMD5(String message) {
         String md5str = "" ;
         try {
             //1 创建一个提供信息摘要算法的对象,初始化为md5算法对象
             MessageDigest md = MessageDigest.getInstance( "MD5" );
 
             //2 将消息变成byte数组
             byte[] input = message.getBytes();
 
             //3 计算后获得字节数组,这就是那128位了
             byte[] buff = md.digest(input);
 
             //4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串
             md5str = bytesToHex(buff);
 
         } catch (Exception e) {
             e.printStackTrace();
         }
         return md5str;
     }
 
     /**
      * 二进制转十六进制
      * @param bytes
      * @return
      */
     public static String bytesToHex(byte[] bytes) {
         StringBuffer md5str = new StringBuffer();
         //把数组每一字节换成16进制连成md5字符串
         int digital;
         for (int i = 0; i < bytes.length; i++) {
              digital = bytes[i];
 
             if (digital < 0) {
                 digital += 256;
             }
             if (digital < 16){
                 md5str.append( "0" );
             }
             md5str.append(Integer.toHexString(digital));
         }
         return md5str.toString().toUpperCase();
     }
}

第三段:md5实现算法具体分析?

md5是怎样进行加密的这个要分步来讲,举个例子来讲如对一个字符串 "abc" 进行加密,第一步 我们要把他转换成位 (也就是将abc换成二进制形式) 现在假设 “abc”转换为二进制后是 1010000101110101 之后就要对这个二进制字节串(起个名字:bytestr)进行补位,至于怎么补,很简单只要使bytestr的长度补成比 512的倍数(n倍)少64位就成(bytestr.length = n*512 - 64)补的数据规则是1+n个0,(10|100|1000|...) 补的位置是在原来数据之后。这些完成后,还要在其后面补上一个64位的数据当然这个数据也是有规定的这个数据就是原字节串的长度(当然这个长度已被转换成了64位)   至此数据补完这样大家一看就能明白 其实补完后这串正好是512的倍数 512 * N-64+64。

现在的数据长度是512*N 那么,算法需要循环N次,每次使用的数据是date[i],  i

每个512位又划分为16个32位, 
然后算法提供四个变量,变量的初始值是如下情况,(之所以是变量,之后会变哦)
四个32位变量初始化为: 
A=0x01234567 
B=0x89abcdef 
C=0xfedcba98 
D=0x76543210 

接着进行算法的主循环,循环的次数是消息中512位消息分组的数目。 
将上面四个变量复制到别外的变量中:A到a,B到b,C到c,D到d。 
主循环有四轮,每轮很相拟。第一轮进行16次操作。

比如  FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti)<<

每次操作对a,b,c和d中的其中三个作一次非线性函数运算(F(b,c,d)),然后将所得结果加上第四个变量(a+)文本的一个子分组(Mj) 一个常数(ti)。(实际上是计算结果加上三个数)

再将所得结果向右环移一个不定的数(s)(16次操作有16个确定的数,并不是随机),并加上a,b,c或d中之一(b+)

最后用该结果取代a,b,c或d中之一(a=)。 
以一下是每次操作FF中用了的四个非线性函数(每轮一个)。
F(X,Y,Z)=(X&Y)|((~X)&Z) 第一轮FF 用F(x,y,z)
G(X,Y,Z)=(X&Z)|(Y&(~Z)) 第二轮GG 用了G(x,y,z)

H(X,Y,Z)=X^Y^Z              第三轮HH用了H函数
I(X,Y,Z)=Y^(X|(~Z)) 地四轮I用了I函数
(&是与,|是或,~是非,^是异或) 


设Mj表示消息的第j个子分组(从0到15),<<
FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti)<<
GG(a,b,c,d,Mj,s,ti)表示a=b+((a+(G(b,c,d)+Mj+ti)<<
HH(a,b,c,d,Mj,s,ti)表示a=b+((a+(H(b,c,d)+Mj+ti)<<
II(a,b,c,d,Mj,s,ti)表示a=b+((a+(I(b,c,d)+Mj+ti)<<
这四轮(共64步)分别如下: 
第一轮  全部是调FF 函数,FF 函数主要是调了F非线性函数,
FF(a,b,c,d,M0,7,0xd76aa478) 
FF(d,a,b,c,M1,12,0xe8c7b756) 
FF(c,d,a,b,M2,17,0x242070db) 
FF(b,c,d,a,M3,22,0xc1bdceee) 
FF(a,b,c,d,M4,7,0xf57c0faf) 
FF(d,a,b,c,M5,12,0x4787c62a) 
FF(c,d,a,b,M6,17,0xa8304613) 
FF(b,c,d,a,M7,22,0xfd469501) 
FF(a,b,c,d,M8,7,0x698098d8) 
FF(d,a,b,c,M9,12,0x8b44f7af) 
FF(c,d,a,b,M10,17,0xffff5bb1) 
FF(b,c,d,a,M11,22,0x895cd7be) 
FF(a,b,c,d,M12,7,0x6b901122) 
FF(d,a,b,c,M13,12,0xfd987193) 
FF(c,d,a,b,M14,17,0xa679438e) 
FF(b,c,d,a,M15,22,0x49b40821) 
第二轮  全部是调GG 函数,GG函数只调用了G线性函数
GG(a,b,c,d,M1,5,0xf61e2562) 
GG(d,a,b,c,M6,9,0xc040b340) 
GG(c,d,a,b,M11,14,0x265e5a51) 
GG(b,c,d,a,M0,20,0xe9b6c7aa) 
GG(a,b,c,d,M5,5,0xd62f105d) 
GG(d,a,b,c,M10,9,0x02441453) 
GG(c,d,a,b,M15,14,0xd8a1e681) 
GG(b,c,d,a,M4,20,0xe7d3fbc8) 
GG(a,b,c,d,M9,5,0x21e1cde6) 
GG(d,a,b,c,M14,9,0xc33707d6) 
GG(c,d,a,b,M3,14,0xf4d50d87) 
GG(b,c,d,a,M8,20,0x455a14ed) 
GG(a,b,c,d,M13,5,0xa9e3e905) 
GG(d,a,b,c,M2,9,0xfcefa3f8) 
GG(c,d,a,b,M7,14,0x676f02d9) 
GG(b,c,d,a,M12,20,0x8d2a4c8a) 
第三轮   
HH(a,b,c,d,M5,4,0xfffa3942) 
HH(d,a,b,c,M8,11,0x8771f681) 
HH(c,d,a,b,M11,16,0x6d9d6122) 
HH(b,c,d,a,M14,23,0xfde5380c) 
HH(a,b,c,d,M1,4,0xa4beea44) 
HH(d,a,b,c,M4,11,0x4bdecfa9) 
HH(c,d,a,b,M7,16,0xf6bb4b60) 
HH(b,c,d,a,M10,23,0xbebfbc70) 
HH(a,b,c,d,M13,4,0x289b7ec6) 
HH(d,a,b,c,M0,11,0xeaa127fa) 
HH(c,d,a,b,M3,16,0xd4ef3085) 
HH(b,c,d,a,M6,23,0x04881d05) 
HH(a,b,c,d,M9,4,0xd9d4d039) 
HH(d,a,b,c,M12,11,0xe6db99e5) 
HH(c,d,a,b,M15,16,0x1fa27cf8) 
HH(b,c,d,a,M2,23,0xc4ac5665) 
第四轮 
II(a,b,c,d,M0,6,0xf4292244) 
II(d,a,b,c,M7,10,0x432aff97) 
II(c,d,a,b,M14,15,0xab9423a7) 
II(b,c,d,a,M5,21,0xfc93a039) 
II(a,b,c,d,M12,6,0x655b59c3) 
II(d,a,b,c,M3,10,0x8f0ccc92) 
II(c,d,a,b,M10,15,0xffeff47d) 
II(b,c,d,a,M1,21,0x85845dd1) 
II(a,b,c,d,M8,6,0x6fa87e4f) 
II(d,a,b,c,M15,10,0xfe2ce6e0) 
II(c,d,a,b,M6,15,0xa3014314) 
II(b,c,d,a,M13,21,0x4e0811a1) 
II(a,b,c,d,M4,6,0xf7537e82) 
II(d,a,b,c,M11,10,0xbd3af235) 
II(c,d,a,b,M2,15,0x2ad7d2bb) 
II(b,c,d,a,M9,21,0xeb86d391) 


以上64步操作中,每一步的位移位数是确定的,每次大循环都一样。加上的常量也是确定的,整个操作中,abcd 依赖上一步的结果,数组m的值依赖实际情况。

操作完之后,abcd 和原来的ABCD 已经变化了几个世界了。
所有这些完成之后,

将A,B,C,D分别加上a,b,c,d。

下一组数据中abcd 初始值和第一组的就不一样了,ABCD已经分别加了abcd。

然后用下一分组数据继续运行算法,最后的输出是A,B,C和D的级联。 


具体实现链接:http://blog.csdn.net/ygy162/article/details/70543967

第四段:对于md5的一些问题?

(大家可选择性查看)

1、md5得到的字符串是唯一的么?

答案:不是,不同的字符串可能得到相同的md5值 md5 是一个32位的16进制的字符A-Z0-9组成  那么就有36的32次方种可能,但是毕竟不是唯一的。

2、什么叫不可逆?

答案:就是破解者,根据密文无法得到原文。

3、这种不可逆是怎么实现的?

我们知道在md5算法中,有位移这种操作,比如说step1 的数据移动了8位,那么要查出来就原来的值,就有8个分支,而step2的结果依赖step1的,所以我们的四轮操作中,每轮16次操作,每次操作都有位移,

假如step1 位移了8,step2-step16 都是8 那么光这一轮操作就产生了,8的16次方种可能。而我们操作却有4轮就是8的64次方种可能。所以要逆推出原始的原文,代价很大。




你可能感兴趣的:(java)