`
什么世道
  • 浏览: 219290 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

MD5算法分析及java代码实现

阅读更多

MD5算法分析及其java代码实现

 

    上一篇博文深入分析了java JDK中的java.util.HashMap类,其实哈希表在日常生活中用的十分广泛,从到数据存储,文件加密,数字签名。本篇博文主要介绍利用散列实现MD5加密算法。

 

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

 

    在MD5算法中,首先需要对信息进行填充,使其位长对512求余的结果等于448。因此,信息的位长(Bits Length)将被扩展至N*512+448,N为一个非负整数,N可以是零。填充的方法如下,在信息的后面填充一个1和剩余的0,直到满足上面的条件时才停止用0对信息的填充。然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,现在的信息的位长=N*512+448+64=(N+1)*512

即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。

如下图:



 

MD5初始的128位值为初试链接变量,为4组8位16进制数。分别为:

A=0x67452301

B=0xefcdab89

C=0x98badcfe

D=0x98badcfe

在java中用数组封装:

 

private long[] state = new long[4]; // state (ABCD)
		state[0] = 0x67452301L;
		state[1] = 0xefcdab89L;
		state[2] = 0x98badcfeL;
		state[3] = 0x10325476L;

 

 

 

 

基本处理思想:初始为128个bit 信息,将128bit 初始信息与分割后的512bit 数据经过4组16次hash循环算法,得到128bit 的新信息,依次循环,直到与最后一组512 bit的数据hash算法后,就得到的整个文件的MD5值。






 

 

    MD5主循环有四轮,每轮循环都很相似。第一轮进行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^Z

I(X,Y,Z)=Y^(X|(~Z))

 

将其用java代码实现:

 

/**
 * F, G, H ,I 是4个基本的MD5函数 把它们封装成private方法,名字保持一致。
 * 
 * @param x
 * @param y
 * @param z
 * @return
 */
private long F(long x, long y, long z) {
	return (x & y) | ((~x) & z);

}

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

}

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

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

 

 

进一步位运算: FF, GG, HH和II

 

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)

Ⅱ(a,b,c,d,Mj,s,ti)表示 a = b + ((a + I(b,c,d) + Mj + ti) << s)

 

Mj表示消息的第j个子分组(从0到15),常数ti是2^32*abs(sin(i))的整数部分,i取值从1到64

 

 作用如下图:

 

 



 

 


java代码实现:

 

/**
 * FF,GG,HH和II将调用F,G,H,I进行近一步变换 FF, GG, HH和II
 * 
 * @param a
 * @param b
 * @param c
 * @param d
 * @param Mj : 第j个子分组
 * @param s : 左移位数
 * @param ac : 2^32 * abs(sin(i))的整数部分,i取值从1到64,单位是弧度。
 * @return
 */
private long FF(long a, long b, long c, long d, long Mj, long s, long ac) {
	a += F(b, c, d) + Mj + ac;
	a = ((int) a << s) | ((int) a >>> (32 - s));
	a += b;
	return a;
}

private long GG(long a, long b, long c, long d, long Mj, long s, long ac) {
	a += G(b, c, d) + Mj + ac;
	a = ((int) a << s) | ((int) a >>> (32 - s));
	a += b;
	return a;
}

private long HH(long a, long b, long c, long d, long Mj, long s, long ac) {
	a += H(b, c, d) + Mj + ac;
	a = ((int) a << s) | ((int) a >>> (32 - s));
	a += b;
	return a;
}

private long II(long a, long b, long c, long d, long Mj, long s, long ac) {
	a += I(b, c, d) + Mj + ac;
	a = ((int) a << s) | ((int) a >>> (32 - s));
	a += b;
	return a;
}

 

 

循环哈希算法

 

第一轮
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(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)
第四轮
Ⅱ(a,b,c,d,M0,6,0xf4292244)
Ⅱ(d,a,b,c,M7,10,0x432aff97)
Ⅱ(c,d,a,b,M14,15,0xab9423a7)
Ⅱ(b,c,d,a,M5,21,0xfc93a039)
Ⅱ(a,b,c,d,M12,6,0x655b59c3)
Ⅱ(d,a,b,c,M3,10,0x8f0ccc92)
Ⅱ(c,d,a,b,M10,15,0xffeff47d)
Ⅱ(b,c,d,a,M1,21,0x85845dd1)
Ⅱ(a,b,c,d,M8,6,0x6fa87e4f)
Ⅱ(d,a,b,c,M15,10,0xfe2ce6e0)
Ⅱ(c,d,a,b,M6,15,0xa3014314)
Ⅱ(b,c,d,a,M13,21,0x4e0811a1)
Ⅱ(a,b,c,d,M4,6,0xf7537e82)
Ⅱ(d,a,b,c,M11,10,0xbd3af235)
Ⅱ(c,d,a,b,M2,15,0x2ad7d2bb)
Ⅱ(b,c,d,a,M9,21,0xeb86d391)

 

 

为了方便期间,我们定义一个所用到的s用4 * 4的矩形来存储。

上面的部分用java代码实现:

 

/**
 * MD5核心变换程序,有md5Update调用
 * @param block 分块的原始字节
 */
private void md5Transform(byte block[]) {
	long a = state[0], b = state[1], c = state[2], d = state[3];
	long[] x = new long[16];

	Decode(x, block, 64);//把long类型(64bit)按顺序拆成byte数组

	/* Round 1 */
	a = FF(a, b, c, d, x[0], S11, 0xd76aa478L); /* 1 */
	d = FF(d, a, b, c, x[1], S12, 0xe8c7b756L); /* 2 */
	c = FF(c, d, a, b, x[2], S13, 0x242070dbL); /* 3 */
	b = FF(b, c, d, a, x[3], S14, 0xc1bdceeeL); /* 4 */
	a = FF(a, b, c, d, x[4], S11, 0xf57c0fafL); /* 5 */
	d = FF(d, a, b, c, x[5], S12, 0x4787c62aL); /* 6 */
	c = FF(c, d, a, b, x[6], S13, 0xa8304613L); /* 7 */
	b = FF(b, c, d, a, x[7], S14, 0xfd469501L); /* 8 */
	a = FF(a, b, c, d, x[8], S11, 0x698098d8L); /* 9 */
	d = FF(d, a, b, c, x[9], S12, 0x8b44f7afL); /* 10 */
	c = FF(c, d, a, b, x[10], S13, 0xffff5bb1L); /* 11 */
	b = FF(b, c, d, a, x[11], S14, 0x895cd7beL); /* 12 */
	a = FF(a, b, c, d, x[12], S11, 0x6b901122L); /* 13 */
	d = FF(d, a, b, c, x[13], S12, 0xfd987193L); /* 14 */
	c = FF(c, d, a, b, x[14], S13, 0xa679438eL); /* 15 */
	b = FF(b, c, d, a, x[15], S14, 0x49b40821L); /* 16 */

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

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

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

	state[0] += a;
	state[1] += b;
	state[2] += c;
	state[3] += d;
}

 

经过以上hash算法,就可以得到文件的MD5值了、、、

 

为了验证程序的正确性:提供几个常见字符串的MD5值: 

空文的散列为:MD5("") = d41d8cd98f00b204e9800998ecf8427e

 

MD5("abc") = 900150983cd24fb0d6963f7d28e17f72

 

参考资料:http://www.ietf.org/rfc/rfc1321.txt

 

对数据结构还不是特别熟悉,希望大家多多支持和指正。

 

 

 

  • 大小: 47.1 KB
  • 大小: 120.9 KB
  • 大小: 66.1 KB
  • 大小: 120.2 KB
  • 大小: 52 KB
  • 大小: 35.9 KB
0
0
分享到:
评论

相关推荐

    Android编程之MD5加密算法实例分析

    本文实例分析了Android编程之MD5加密算法。分享给大家供大家参考,具体如下: Android MD5加密算与J2SE平台一模一样,因为Android 平台支持 java.security.MessageDigest这个包。实际上与J2SE平台一模一样。 算法...

    JAVA上百实例源码以及开源项目源代码

    Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像、数据初始化、矩阵乘法、坐标旋转、判断是否是顺时针方向排列、鼠标按下、放开时的动作等,都可在本源码中得以体现。 Java...

    JAVA上百实例源码以及开源项目

    Java源代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像、数据初始化、矩阵乘法、坐标旋转、判断是否是顺时针方向排列、鼠标按下、放开时的动作等,都可在本源码中得以体现。 Java...

    多种算法融合的推荐系统Java源码实现:用户与物品协同过滤、标签推荐与潜在因子分析

    项目简介:本项目采用Java语言实现了一套融合多种推荐算法的系统。该系统深入结合用户与物品协同过滤、标签推荐及潜在因子分析技术,以提供更为精准的个性化推荐服务。项目文件总计111个,主要包括76个Java源代码...

    java开源包8

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包4

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包7

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包5

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包10

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包3

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包11

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包6

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包9

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    java开源包101

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

    毕业设计-基于Java的两个通用安全模块的设计与实现(源代码+论文)

    本文详细介绍了基于口令的身份认证与文件安全传输两个通用安全模块的设计原理和实现过程,分析了当前口令保存的安全性,提出了运用MD5算法等对口令进行处理,并将处理结果保存在数据库中的方法。同时为了进一步增强...

    基于Java的两个通用安全模块的设计与实现(源代码+论文).zip

    本文详细介绍了基于口令的身份认证与文件安全传输两个通用安全模块的设计原理和实现过程,分析了当前口令保存的安全性,提出了运用MD5算法等对口令进行处理,并将处理结果保存在数据库中的方法。同时为了进一步增强...

    [计算机毕设]基于java的两个通用安全模块系统设计与实现(源代码+项目报告).zip

    本文详细介绍了基于口令的身份认证与文件安全传输两个通用安全模块的设计原理和实现过程,分析了当前口令保存的安全性,提出了运用MD5算法等对口令进行处理,并将处理结果保存在数据库中的方法。同时为了进一步增强...

    基于java的两个通用安全模块系统设计与实现毕业设计(源代码+说明报告)

    本文详细介绍了基于口令的身份认证与文件安全传输两个通用安全模块的设计原理和实现过程,分析了当前口令保存的安全性,提出了运用MD5算法等对口令进行处理,并将处理结果保存在数据库中的方法。同时为了进一步增强...

    java开源包1

    用来计算 MD5、SHA 哈希算法的 Java 类库,支持 "MD5", "SHA", "SHA-1", "SHA-256", "SHA-384", "SHA-512". 高性能RPC框架 nfs-rpc nfs-rpc是一个集成了各种知名通信框架的高性能RPC框架,目前其最好的性能为在采用...

Global site tag (gtag.js) - Google Analytics