MD5校验工具开发

勒索病毒施虐全球之际,信息,文件和软件的安全性受到了人们关注。MD5校验对于过滤病毒文件,防止病毒传播十分有用。

Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data SecurityInc. April 1992)。

MD5即Message-DigestAlgorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法哈希算法),主流编程语言普遍已有MD5实现。将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3MD4

MD5算法具有以下特点:

1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。

2、容易计算:从原数据计算出MD5值很容易。

3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。

4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。除了MD5以外,其中比较有名的还有sha-1RIPEMD以及Haval等。


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)先认识四个线性函数(&是与,|是或,~是非,^是异或)

  1. F(X,Y,Z)=(X&Y)|((~X)&Z)  
  2. G(X,Y,Z)=(X&Z)|(Y&(~Z))  
  3. H(X,Y,Z)=X^Y^Z  
  4. I(X,Y,Z)=Y^(X|(~Z))  

  3)设Mj表示消息的第j个子分组(从0到15),<<<s表示循环左移s位,则四种操作为:

  1. FF(a,b,c,d,Mj,s,ti)表示a=b+((a+F(b,c,d)+Mj+ti)<<<s)  
  2. GG(a,b,c,d,Mj,s,ti)表示a=b+((a+G(b,c,d)+Mj+ti)<<<s)  
  3. HH(a,b,c,d,Mj,s,ti)表示a=b+((a+H(b,c,d)+Mj+ti)<<<s)  
  4. II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)   

4)四轮运算

[cpp] view plain copy

  1. 第一轮  
  2. a=FF(a,b,c,d,M0,7,0xd76aa478)  
  3.  b=FF(d,a,b,c,M1,12,0xe8c7b756)  
  4.  c=FF(c,d,a,b,M2,17,0x242070db)  
  5.  d=FF(b,c,d,a,M3,22,0xc1bdceee)  
  6.  a=FF(a,b,c,d,M4,7,0xf57c0faf)  
  7.  b=FF(d,a,b,c,M5,12,0x4787c62a)  
  8.  c=FF(c,d,a,b,M6,17,0xa8304613)  
  9.  d=FF(b,c,d,a,M7,22,0xfd469501)  
  10.  a=FF(a,b,c,d,M8,7,0x698098d8)  
  11.  b=FF(d,a,b,c,M9,12,0x8b44f7af)  
  12.  c=FF(c,d,a,b,M10,17,0xffff5bb1)  
  13.  d=FF(b,c,d,a,M11,22,0x895cd7be)  
  14.  a=FF(a,b,c,d,M12,7,0x6b901122)  
  15.  b=FF(d,a,b,c,M13,12,0xfd987193)  
  16.  c=FF(c,d,a,b,M14,17,0xa679438e)  
  17.  d=FF(b,c,d,a,M15,22,0x49b40821)  
  18.   
  19. 第二轮  
  20. a=GG(a,b,c,d,M1,5,0xf61e2562)  
  21.  b=GG(d,a,b,c,M6,9,0xc040b340)  
  22.  c=GG(c,d,a,b,M11,14,0x265e5a51)  
  23.  d=GG(b,c,d,a,M0,20,0xe9b6c7aa)  
  24.  a=GG(a,b,c,d,M5,5,0xd62f105d)  
  25.  b=GG(d,a,b,c,M10,9,0x02441453)  
  26.  c=GG(c,d,a,b,M15,14,0xd8a1e681)  
  27.  d=GG(b,c,d,a,M4,20,0xe7d3fbc8)  
  28.  a=GG(a,b,c,d,M9,5,0x21e1cde6)  
  29.  b=GG(d,a,b,c,M14,9,0xc33707d6)  
  30.  c=GG(c,d,a,b,M3,14,0xf4d50d87)  
  31.  d=GG(b,c,d,a,M8,20,0x455a14ed)  
  32.  a=GG(a,b,c,d,M13,5,0xa9e3e905)  
  33.  b=GG(d,a,b,c,M2,9,0xfcefa3f8)  
  34.  c=GG(c,d,a,b,M7,14,0x676f02d9)  
  35.  d=GG(b,c,d,a,M12,20,0x8d2a4c8a)  
  36.   
  37. 第三轮  
  38. a=HH(a,b,c,d,M5,4,0xfffa3942)  
  39.  b=HH(d,a,b,c,M8,11,0x8771f681)  
  40.  c=HH(c,d,a,b,M11,16,0x6d9d6122)  
  41.  d=HH(b,c,d,a,M14,23,0xfde5380c)  
  42.  a=HH(a,b,c,d,M1,4,0xa4beea44)  
  43.  b=HH(d,a,b,c,M4,11,0x4bdecfa9)  
  44.  c=HH(c,d,a,b,M7,16,0xf6bb4b60)  
  45.  d=HH(b,c,d,a,M10,23,0xbebfbc70)  
  46.  a=HH(a,b,c,d,M13,4,0x289b7ec6)  
  47.  b=HH(d,a,b,c,M0,11,0xeaa127fa)  
  48.  c=HH(c,d,a,b,M3,16,0xd4ef3085)  
  49.  d=HH(b,c,d,a,M6,23,0x04881d05)  
  50.  a=HH(a,b,c,d,M9,4,0xd9d4d039)  
  51.  b=HH(d,a,b,c,M12,11,0xe6db99e5)  
  52.  c=HH(c,d,a,b,M15,16,0x1fa27cf8)  
  53.  d=HH(b,c,d,a,M2,23,0xc4ac5665)  
  54.   
  55. 第四轮  
  56. a=II(a,b,c,d,M0,6,0xf4292244)  
  57.  b=II(d,a,b,c,M7,10,0x432aff97)  
  58.  c=II(c,d,a,b,M14,15,0xab9423a7)  
  59.  d=II(b,c,d,a,M5,21,0xfc93a039)  
  60.  a=II(a,b,c,d,M12,6,0x655b59c3)  
  61.  b=II(d,a,b,c,M3,10,0x8f0ccc92)  
  62.  c=II(c,d,a,b,M10,15,0xffeff47d)  
  63.  d=II(b,c,d,a,M1,21,0x85845dd1)  
  64.  a=II(a,b,c,d,M8,6,0x6fa87e4f)  
  65.  b=II(d,a,b,c,M15,10,0xfe2ce6e0)  
  66.  c=II(c,d,a,b,M6,15,0xa3014314)  
  67.  d=II(b,c,d,a,M13,21,0x4e0811a1)  
  68.  a=II(a,b,c,d,M4,6,0xf7537e82)  
  69.  b=II(d,a,b,c,M11,10,0xbd3af235)  
  70.  c=II(c,d,a,b,M2,15,0x2ad7d2bb)  
  71.  d=II(b,c,d,a,M9,21,0xeb86d391)  

 常数ti可以如下选择: 
在第i步中,ti是4294967296*abs(sin(i))的整数部分,i的单位是弧度。 
(2的32次方) 

5)每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环。


代码实现

public class Md5Util {
	// 标准的构造函数,调用md5Init函数进行初始化工作
	public Md5Util() {
		md5Init();
		return;
	}

	// RFC1321中定义的标准4*4矩阵的常量定义。
	static final int S11 = 7, S12 = 12, S13 = 17, S14 = 22;
	static final int S21 = 5, S22 = 9, S23 = 14, S24 = 20;
	static final int S31 = 4, S32 = 11, S33 = 16, S34 = 23;
	static final int S41 = 6, S42 = 10, S43 = 15, S44 = 21;

	// 按RFC1321标准定义不可变byte型数组PADDING
	static final byte[] PADDING = { -128, 0, 0, 0, 0, 0, 0, 0,

			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

	// MD5计算过程中的3组核心数据,采用数组形式存放
	private long[] state = new long[4]; // 计算状态(分别对应a b c d)

	private byte[] buffer = new byte[64]; // 分配64个字节私有缓冲区

	private long[] count = new long[2]; // 位个数

	// 最新一次计算结果的16进制ASCII字符串表示,代表了16个字符串形式的MD5值
	public String resultStr;

	// 最新一次计算结果的2进制数组表示,一共16个字节,代表了128 bit形式的MD5值
	public byte[] digest = new byte[16];

	/**
	 * 获得两次MD5加密的字符串
	 * 
	 * @param str
	 * @return
	 */
	public String getTwiceMD5ofString(String str) {
		return getMD5ofStr(getMD5ofStr(str));
	}

	/**
	 * MD5_Encoding类提供的主要的接口函数getMD5ofStr,用来进行数
	 * 
	 * 据加密变换。调用其可对任意字符串进行加密运算,并以字符串形式返回
	 * 
	 * 加密结果。
	 * 
	 * @param in
	 * @return
	 */
	public String getMD5ofStr(String in) {
		md5Init(); // 初始化
		md5Update(in.getBytes(), in.length());// 调用MD5的主计算过程
		md5Final(); // 输出结果到digest数组中
		for (int i = 0; i < 16; i++) {
			resultStr += byteToHEX(digest[i]); // 将digest数组中的每个byte型数据转为16进制形式的字符串
		}
		return resultStr;
	}

	// md5初始化函数.初始化核心变量.
	private void md5Init() {
		state[0] = 0x67452301L; // 定义state为RFC1321中定义的标准幻数
		state[1] = 0xefcdab89L; // 定义state为RFC1321中定义的标准幻数
		state[2] = 0x98badcfeL; // 定义state为RFC1321中定义的标准幻数
		state[3] = 0x10325476L; // 定义state为RFC1321中定义的标准幻数
		count[0] = count[1] = 0L; // 初始化为0
		resultStr = "";// 初始化resultStr字符串为空
		for (int i = 0; i < 16; i++)
			digest[i] = 0;// 初始化digest数组元素为0
		return;
	}

	// 定义F G H I 为4个基数 ,即为4个基本的MD5函数,进行简单的位运算

	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调用F,G,H,I函数进行进一步变换
	private long FF(long a, long b, long c, long d, long x, long

	s, long ac) {
		a += F(b, c, d) + x + ac;
		a = ((int) a << s) | ((int) a >>> (32 - s)); // 这里long型数据右移时使用无符号右移运算符>>>
		a += b;
		return a;
	}

	private long GG(long a, long b, long c, long d, long x, long

	s, long ac) {
		a += G(b, c, d) + x + ac;
		a = ((int) a << s) | ((int) a >>> (32 - s)); // 这里long型数据右移时使用无符号右移运算符>>>
		a += b;
		return a;
	}

	private long HH(long a, long b, long c, long d, long x, long

	s, long ac) {
		a += H(b, c, d) + x + ac;
		a = ((int) a << s) | ((int) a >>> (32 - s));// 这里long型数据右移时使用无符号右移运算符>>>
		a += b;
		return a;
	}

	private long II(long a, long b, long c, long d, long x, long

	s, long ac) {
		a += I(b, c, d) + x + ac;
		a = ((int) a << s) | ((int) a >>> (32 - s));// 这里long型数据右移时使用无符号右移运算符>>>
		a += b;
		return a;
	}

	// MD5的主计算过程,input是需要变换的二进制字节串,inputlen是长度

	private void md5Update(byte[] input, int inputLen) {
		int i = 0, index, partLen;
		byte[] block = new byte[64]; // 分配64个字节缓冲区
		// 根据count计算index值。这里long型数据右移时使用无符号右移运算符>>>
		index = (int) (count[0] >>> 3) & 0x3F;
		if ((count[0] += (inputLen << 3)) < (inputLen << 3))
			count[1]++;
		count[1] += (inputLen >>> 29); // 这里int型数据右移时使用无符号右移运算符>>>
		partLen = 64 - index; // 计算partLen值
		if (inputLen >= partLen) {
			md5Memcpy(buffer, input, index, 0, partLen);
			md5Transform(buffer);
			for (i = partLen; i + 63 < inputLen; i += 64) {
				md5Memcpy(block, input, 0, i, 64);
				md5Transform(block);
			}
			index = 0;
		} else
			i = 0;
		md5Memcpy(buffer, input, index, i, inputLen - i);
	}

	// 整理和填写输出结果,结果放到数组digest中。
	private void md5Final() {
		byte[] bits = new byte[8];
		int index, padLen;
		Encode(bits, count, 8);
		index = (int) (count[0] >>> 3) & 0x3f; // 这里long型数据右移时使用无符号右移运算符>>>
		padLen = (index < 56) ? (56 - index) : (120 - index);
		md5Update(PADDING, padLen);
		md5Update(bits, 8);
		Encode(digest, state, 16);
	}

	// byte数组的块拷贝函数,将input数组中的起始位置为inpos,长
	// 度len的数据拷贝到output数组起始位置outpos处。
	private void md5Memcpy(byte[] output, byte[] input, int outpos, int inpos, int len) {
		int i;
		for (i = 0; i < len; i++)
			output[outpos + i] = input[inpos + i];
	}

	// MD5核心变换计算程序,由md5Update函数调用,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);
		// 进行4级级联运算
		// 第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 */

		// 第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 */

		// 第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 */

		// 第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],state[1],state[2],state[3]
		state[0] += a;
		state[1] += b;
		state[2] += c;
		state[3] += d;
	}

	// 把byte型数据转换为无符号long型数据
	private static long byteToul(byte b) {
		return b > 0 ? b : (b & 0x7F + 128);
	}

	// 把byte类型的数据转换成十六进制ASCII字符表示
	private static String byteToHEX(byte in) {
		char[] DigitStr = { '0', '1', '2', '3', '4', '5', '6',

				'7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		char[] out = new char[2];
		out[0] = DigitStr[(in >> 4) & 0x0F]; // 取高4位
		out[1] = DigitStr[in & 0x0F]; // 取低4位
		String s = new String(out);
		return s;
	}

	// 将long型数组按顺序拆成byte型数组,长度为len
	private void Encode(byte[] output, long[] input, int len) {
		int i, j;
		for (i = 0, j = 0; j < len; i++, j += 4) {
			output[j] = (byte) (input[i] & 0xffL);
			output[j + 1] = (byte) ((input[i] >>> 8) & 0xffL);
			output[j + 2] = (byte) ((input[i] >>> 16) & 0xffL);
			output[j + 3] = (byte) ((input[i] >>> 24) & 0xffL);
		}
	}

	// 将byte型数组按顺序合成long型数组,长度为len
	private void Decode(long[] output, byte[] input, int len) {
		int i, j;
		for (i = 0, j = 0; j < len; i++, j += 4)
			output[i] = byteToul(input[j]) | (byteToul(input[j +

			1]) << 8) | (byteToul(input[j + 2]) << 16) | (byteToul(input[j +

			3]) << 24);
		return;
	}

	public static String getMd5ByFile(File file) {
		String value = null;
		FileInputStream in = null;
		try {
			in = new FileInputStream(file);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			if (file.length() < Integer.MAX_VALUE) {
				MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
				md5.update(byteBuffer);
			} 
			else 
			{
				byte[] buffer = new byte[8192];
				int length;
				while ((length = in.read(buffer)) != -1) {
					md5.update(buffer, 0, length);
				}
			}
			BigInteger bi = new BigInteger(1, md5.digest());
			value = bi.toString(16);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return value;
	}
	
}


public class frame extends JFrame {

    private JPanel contentPane;
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    frame frame = new frame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    int win_X = 100, win_Y=100, win_W=600, win_H=400;
    int title_W=154, title_H=15, title_X = win_W/2-title_W/2, title_Y=20;
    
    int buttonX=80, buttonY=80+20, buttonW=80, buttonH=30, buttonSPACE=20;
    int file_X=100, file_Y=20+20, file_W=400, file_H=21;
    int fileL_X=20, fileL_Y=26+20, fileL_W=84, fileL_H=15;
    int md5_X=100, md5_Y=50+20, md5_W=400, md5_H=21;
    int md5L_X=20, md5L_Y=56+20, md5L_W=84, md5L_H=15;
  
    
    int buttonY2=80+20+220;
    int file_Y2=20+20+130;
    int fileL_Y2=26+20+130;
    int md5_Y2=50+20+130;
    int md5L_Y2=56+20+130;
    int md5_H2=100;
    
    int title_Y2=20+130;
    String Logpath;
    public frame() {
        setBackground(Color.PINK);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(win_X, win_Y, win_W, win_H);
        contentPane = new JPanel();
        contentPane.setBackground(Color.GRAY);
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        JLayeredPane layeredPane = new JLayeredPane();
        layeredPane.setBackground(Color.CYAN);
        contentPane.add(layeredPane, BorderLayout.CENTER);

        JTextField textField = new JTextField();
        textField.setBounds(file_X, file_Y, file_W, file_H);
        layeredPane.add(textField);
        textField.setColumns(10);

        JTextField textField_1 = new JTextField();
        textField_1.setBounds(md5_X, md5_Y, md5_W, md5_H);
        layeredPane.add(textField_1);
        textField_1.setColumns(10);

        JLabel lblSetFile = new JLabel("设置文件");
        lblSetFile.setBounds(fileL_X, fileL_Y, fileL_W, fileL_H);
        layeredPane.add(lblSetFile);

        JLabel lblMd5 = new JLabel("设置Md5");
        lblMd5.setBounds(md5L_X, md5L_Y, md5L_W, md5L_H);
        layeredPane.add(lblMd5);
        
        /**
         * JFileChooser 是Java Swing提供的文件选择对话框
         * */
        
        JFileChooser jfc = new JFileChooser();//构造一个指向用户默认目录的 JFileChooser。
        Button btnSet = new Button("选择文件");//Browse按钮用于获取文件
        btnSet.addActionListener(new ActionListener() {//Browse按钮 的 监听事件
			public void actionPerformed(ActionEvent arg0) {
				int result = jfc.showOpenDialog(null);// 弹出一个 "Open File"
														// 文件选择器对话框。
				String filepath = ""; // 初始化变量filepath(文件路径)
				if (result == JFileChooser.APPROVE_OPTION) {// JFileChooser.APPROVE_OPTION是个整型
					// 常量,代表0,当返回0值时,执行相关操作。
					filepath = jfc.getSelectedFile().getAbsolutePath();// 获得你选择的文件的绝对路径
					textField.setText(filepath);// 将选择的文件的绝对路径在文本框textField中显示。
				}

				String ff = textField.getText();
				int backslashIndex = ff.lastIndexOf('\\');
				// 路径名是最后一个'/'之前的字符
				Logpath = ff.substring(0, backslashIndex + 1);
				System.out.println(Logpath);
			}
        });
        btnSet.setBounds(buttonX, buttonY, buttonW, buttonH);
        layeredPane.add(btnSet);

        Button btnMd = new Button("生成MD5");//********Count Md5用于计算MD5值***********
        btnMd.addActionListener(new ActionListener() {//Count Md5按钮的监听事件
            public void actionPerformed(ActionEvent e) {
                File file = jfc.getSelectedFile();//返回选中的文件
                String filemd5 = Md5Util.getMd5ByFile(file);//得到文件的MD5值
                textField_1.setText(filemd5);//将文件的MD5值在文本框textField中显示出来。
            }
        });
        btnMd.setBounds(buttonX+buttonW+buttonSPACE, buttonY, buttonW, buttonH);
        layeredPane.add(btnMd);
   

        Button checkMd = new Button("校验MD5");//********Count Md5用于计算MD5值***********
        checkMd.addActionListener(new ActionListener() {//Count Md5按钮的监听事件
            public void actionPerformed(ActionEvent e) {
                File file = jfc.getSelectedFile();//返回选中的文件
                String filemd5 = Md5Util.getMd5ByFile(file);//得到文件的MD5值
                String checkMd5 = textField_1.getText();
                Toolkit.getDefaultToolkit().beep();
                if (filemd5.equals(checkMd5)){
                JOptionPane.showMessageDialog(null, "MD5校验正确", "MD5校验正确",JOptionPane.INFORMATION_MESSAGE);
                }else{
                	JOptionPane.showMessageDialog(null, "MD5校验不对", "MD5校验不对",JOptionPane.INFORMATION_MESSAGE);	
                }
            }
        });
        checkMd.setBounds(buttonX+buttonW*2+buttonSPACE*2, buttonY, buttonW, buttonH);
        layeredPane.add(checkMd);
        
        Button saveMd = new Button("保存MD5");//********Count Md5用于计算MD5值***********
        saveMd.addActionListener(new ActionListener() {//Count Md5按钮的监听事件
            public void actionPerformed(ActionEvent e) {
                File file = jfc.getSelectedFile();//返回选中的文件
                String filemd5 = Md5Util.getMd5ByFile(file);//得到文件的MD5值
                String checkMd5 = textField_1.getText();
                String str=file.getPath()+"|"+filemd5;
                writeCheckSum(Logpath+"md5checksum.txt", str);
            }
        });
        saveMd.setBounds(buttonX+buttonW*3+buttonSPACE*3, buttonY, buttonW, buttonH);
        layeredPane.add(saveMd);
        
      

        
        JLabel title = new JLabel("文件MD5");
        title.setBounds(title_X, title_Y, title_W, title_H);
        layeredPane.add(title);
        //****************************************************************************************//\
        JTextField textField2 = new JTextField();
        textField2.setAutoscrolls(true);
        textField2.setBounds(file_X, file_Y2, file_W, file_H);
        layeredPane.add(textField2);
        textField2.setColumns(10);

        JTextArea textField_12 = new JTextArea();
        JScrollPane scroll = new JScrollPane(textField_12); 
        scroll.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 
        scroll.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 
        //textField_12.setAutoscrolls(true);
        //textField_12.setLineWrap(true); 
        scroll.setBounds(md5_X, md5_Y2, md5_W, md5_H2);
        //textField_12.setBounds(md5_X, md5_Y2, md5_W, md5_H2);
        //layeredPane.add(textField_12);
        layeredPane.add(scroll);
        //textField_12.setColumns(10);

        JLabel lblSetFile2 = new JLabel("设置文件夹");
        lblSetFile2.setBounds(fileL_X, fileL_Y2, fileL_W, fileL_H);
        layeredPane.add(lblSetFile2);

        JLabel lblMd52 = new JLabel("设置Md5路径");
        lblMd52.setBounds(md5L_X, md5L_Y2, md5L_W, md5L_H);
        layeredPane.add(lblMd52);
       
        
        /**
         * JFileChooser 是Java Swing提供的文件选择对话框
         * */
        JFileChooser jfc2 = new JFileChooser();//构造一个指向用户默认目录的 JFileChooser。
        Button btnSet2 = new Button("选择文件夹");//Browse按钮用于获取文件
        btnSet2.addActionListener(new ActionListener() {//Browse按钮 的 监听事件
			public void actionPerformed(ActionEvent arg0) {

				jfc2.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);// 只能选择目录
				String path = null;
				File f = null;
				int flag = 0;
				try {
					flag = jfc2.showOpenDialog(null);
				} catch (HeadlessException head) {
					System.out.println("Open File Dialog ERROR!");
				}
				if (flag == JFileChooser.APPROVE_OPTION) {
					// 获得该文件
					f = jfc2.getSelectedFile();
					path = f.getPath();
					textField2.setText(path);//将选择的文件的绝对路径在文本框textField中显示。
				}
			}
        });
        btnSet2.setBounds(buttonX, buttonY2, buttonW, buttonH);
        layeredPane.add(btnSet2);

        Button btnMd2 = new Button("生成MD5");//********Count Md5用于计算MD5值***********
        btnMd2.addActionListener(new ActionListener() {//Count Md5按钮的监听事件
            public void actionPerformed(ActionEvent e) {
            	textField_12.setText("");
            	File file = new File(textField2.getText());
        		File[] tempList = file.listFiles();
        		System.out.println("该目录下对象个数:" + tempList.length);
        		StringBuffer sb = new StringBuffer();
        		for (int i = 0; i < tempList.length; i++) {
        			if (tempList[i].isFile()) {
        				if (tempList[i].getName().indexOf("md5checksum") !=0){
        				System.out.println("文     件:" + tempList[i]);
                        String filemd5 = Md5Util.getMd5ByFile(tempList[i]);//得到文件的MD5值
                        //textField_12.setText(sb.toString());//将文件的MD5值在文本框textField中显示出来。\
                        textField_12.append(tempList[i].getName()+"|"+filemd5+"\r\n");
        				}
        			}
        		}
            }
        });
        btnMd2.setBounds(buttonX+buttonW+buttonSPACE, buttonY2, buttonW, buttonH);
        layeredPane.add(btnMd2);
   

        Button checkMd2 = new Button("校验MD5");//********Count Md5用于计算MD5值***********
        checkMd2.addActionListener(new ActionListener() {//Count Md5按钮的监听事件
            public void actionPerformed(ActionEvent e) {
            	/*
                File file = jfc2.getSelectedFile();//返回选中的文件
                String filemd5 = Md5Util.getMd5ByFile(file);//得到文件的MD5值
                String checkMd5 = textField_12.getText();
                Toolkit.getDefaultToolkit().beep();
                if (filemd5.equals(checkMd5)){
                JOptionPane.showMessageDialog(null, "MD5校验正确", "MD5校验正确",JOptionPane.INFORMATION_MESSAGE);
                }else{
                	JOptionPane.showMessageDialog(null, "MD5校验不对", "MD5校验不对",JOptionPane.INFORMATION_MESSAGE);	
                }
                */
            	boolean error=false;
            	String tempstr;
                File file=new File(textField2.getText()+"\\"+"md5checksum.txt");
			    if(!file.exists())
			    {
			    	JOptionPane.showMessageDialog(null, "MD5校验不对", "找不到md5checksum.txt",JOptionPane.INFORMATION_MESSAGE);		  
			    }
                
				try {
					FileInputStream fis;
					fis = new FileInputStream(file);
					BufferedReader br = new BufferedReader(new InputStreamReader(fis));
					while ((tempstr = br.readLine()) != null) {
						System.out.println(">>>>>>>>>>>>>>>" + tempstr);
						if (tempstr.indexOf('|') != -1) {
							String[] s = tempstr.split("\\|");
							System.out.println(">>>>>>>>>>>>>>>" + s[0]);
							System.out.println(">>>>>>>>>>>>>>>" + s[1]);
							System.out.println(">>>>>>>>>>>>>>>" + textField2.getText() + "\\" + s[0]);
							File f = new File(textField2.getText() + "\\" + s[0]);
							System.out.println(">>>>>>>>>>>>>>>" + f.getPath());
							String filemd5 = Md5Util.getMd5ByFile(f);// 得到文件的MD5值
							System.out.println(">>>>>>>>>>>>>>>filemd5=" + filemd5);
							if (!filemd5.equals(s[1])) {
								JOptionPane.showMessageDialog(null, 
										textField2.getText() + "\\" + s[0] + "校验不对", "MD5校验不对",JOptionPane.INFORMATION_MESSAGE);
								error=true;
								break;
							}
						}
					}
					if (!error){
					JOptionPane.showMessageDialog(null, "MD5校验成功", "校验成功", JOptionPane.INFORMATION_MESSAGE);
					}
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
                
                
            }
        });
        checkMd2.setBounds(buttonX+buttonW*2+buttonSPACE*2, buttonY2, buttonW, buttonH);
        layeredPane.add(checkMd2);
        
        Button saveMd2 = new Button("保存MD5");//********Count Md5用于计算MD5值***********
        saveMd2.addActionListener(new ActionListener() {//Count Md5按钮的监听事件
            public void actionPerformed(ActionEvent e) {
              
                String str=textField_12.getText();
                writeCheckSum(textField2.getText()+"\\"+"md5checksum.txt", str);
            }
        });
        saveMd2.setBounds(buttonX+buttonW*3+buttonSPACE*3, buttonY2, buttonW, buttonH);
        layeredPane.add(saveMd2);
        
        
        JLabel title2 = new JLabel("文件夹MD5");
        title2.setBounds(title_X, title_Y2, title_W, title_H);
        layeredPane.add(title2);
    }
    
    public static void getFileList(String path) {
		File file = new File(path);
		File[] tempList = file.listFiles();
		System.out.println("该目录下对象个数:" + tempList.length);
		for (int i = 0; i < tempList.length; i++) {
			if (tempList[i].isFile()) {
				System.out.println("文     件:" + tempList[i]);
			}
		}
	}
    public static void writeCheckSum(String path, String str)
    {
        try
        {
        //String path="/root/test/testfilelog.log";
        File file=new File(path);
        if(!file.exists())
            file.createNewFile();
        //SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        FileOutputStream out=new FileOutputStream(file,false); //如果追加方式用true        
        StringBuffer sb=new StringBuffer();
        //sb.append("-----------"+sdf.format(new Date())+"------------\n");
        sb.append(str+"\n");
        out.write(sb.toString().getBytes("utf-8"));//注意需要转换对应的字符集
        out.close();
        }
        catch(IOException ex)
        {
            System.out.println(ex.getStackTrace());
        }
    }    
}
 


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值