`
hzy3774
  • 浏览: 984865 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

使用MD5算法验证文件完整性或密码正确性

 
阅读更多

          MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法),主流编程语言普遍已有MD5实现。

            将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。

            MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。

          MD5在实际应用中通常有两种用法,一种是计算一个字符串的MD5值,常用于密码相关的操作;另一种是用于计算一个文件的MD5值,一般用于网络传输中验证文件是否出错。

        下面是C语言的MD5计算程序,来自Stardict,网上流行的代码都大同小异:

 

md5.h

 

#ifndef MD5_H
#define MD5_H

#ifdef __cplusplus
extern "C"
{
#endif                          /* __cplusplus */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#ifdef HAVE_STDINT_H
	#include <stdint.h>
	typedef uint32_t uint32;
#else
	/* A.Leo.: this wont work on 16 bits platforms ;) */
	typedef unsigned uint32;
#endif

#define MD5_FILE_BUFFER_LEN 1024

struct MD5Context {
	uint32 buf[4];
	uint32 bits[2];
	unsigned char in[64];
};

void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf,
	       unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context);
void MD5Transform(uint32 buf[4], uint32 const in[16]);

int getBytesMD5(const unsigned char* src, unsigned int length, char* md5);
int getStringMD5(const char* src, char* md5);
int getFileMD5(const char* path, char* md5);

/*
 * This is needed to make RSAREF happy on some MS-DOS compilers.
 */
typedef struct MD5Context MD5_CTX;

#ifdef __cplusplus
}
#endif                          /* __cplusplus */

#endif /* !MD5_H */

 源文件:

md5.c

 

#include <string.h>		/* for memcpy() */
#include <stdio.h>
#include "md5.h"

#ifndef HIGHFIRST
#define byteReverse(buf, len)	/* Nothing */
#else
void byteReverse(unsigned char *buf, unsigned longs);

#ifndef ASM_MD5
/*
 * Note: this code is harmless on little-endian machines.
 */
void byteReverse(unsigned char *buf, unsigned longs)
{
	uint32 t;
	do {
		t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
		((unsigned) buf[1] << 8 | buf[0]);
		*(uint32 *) buf = t;
		buf += 4;
	}while (--longs);
}
#endif
#endif

static void putu32(uint32 data, unsigned char *addr) {
	addr[0] = (unsigned char) data;
	addr[1] = (unsigned char) (data >> 8);
	addr[2] = (unsigned char) (data >> 16);
	addr[3] = (unsigned char) (data >> 24);
}

/*
 * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
 * initialization constants.
 */
void MD5Init(struct MD5Context *ctx) {
	ctx->buf[0] = 0x67452301;
	ctx->buf[1] = 0xefcdab89;
	ctx->buf[2] = 0x98badcfe;
	ctx->buf[3] = 0x10325476;

	ctx->bits[0] = 0;
	ctx->bits[1] = 0;
}

/*
 * Update context to reflect the concatenation of another buffer full
 * of bytes.
 */
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) {
	uint32 t;

	/* Update bitcount */

	t = ctx->bits[0];
	if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
		ctx->bits[1]++; /* Carry from low to high */
	ctx->bits[1] += len >> 29;

	t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */

	/* Handle any leading odd-sized chunks */

	if (t) {
		unsigned char *p = (unsigned char *) ctx->in + t;

		t = 64 - t;
		if (len < t) {
			memcpy(p, buf, len);
			return;
		}
		memcpy(p, buf, t);
		byteReverse(ctx->in, 16);
		MD5Transform(ctx->buf, (uint32 *) ctx->in);
		buf += t;
		len -= t;
	}
	/* Process data in 64-byte chunks */

	while (len >= 64) {
		memcpy(ctx->in, buf, 64);
		byteReverse(ctx->in, 16);
		MD5Transform(ctx->buf, (uint32 *) ctx->in);
		buf += 64;
		len -= 64;
	}

	/* Handle any remaining bytes of data. */

	memcpy(ctx->in, buf, len);
}

/*
 * Final wrapup - pad to 64-byte boundary with the bit pattern 
 * 1 0* (64-bit count of bits processed, MSB-first)
 */
void MD5Final(unsigned char digest[16], struct MD5Context *ctx) {
	unsigned count;
	unsigned char *p;

	/* Compute number of bytes mod 64 */
	count = (ctx->bits[0] >> 3) & 0x3F;

	/* Set the first char of padding to 0x80.  This is safe since there is
	 always at least one byte free */
	p = ctx->in + count;
	*p++ = 0x80;

	/* Bytes of padding needed to make 64 bytes */
	count = 64 - 1 - count;

	/* Pad out to 56 mod 64 */
	if (count < 8) {
		/* Two lots of padding:  Pad the first block to 64 bytes */
		memset(p, 0, count);
		byteReverse(ctx->in, 16);
		MD5Transform(ctx->buf, (uint32 *) ctx->in);

		/* Now fill the next block with 56 bytes */
		memset(ctx->in, 0, 56);
	} else {
		/* Pad block to 56 bytes */
		memset(p, 0, count - 8);
	} byteReverse(ctx->in, 14);

	/* Append length in bits and transform */
	//((uint32 *) ctx->in)[14] = ctx->bits[0];
	//((uint32 *) ctx->in)[15] = ctx->bits[1];
	putu32(ctx->bits[0], ctx->in + 56);
	putu32(ctx->bits[1], ctx->in + 60);

	MD5Transform(ctx->buf, (uint32 *) ctx->in);
	byteReverse((unsigned char *) ctx->buf, 4);
	memcpy(digest, ctx->buf, 16);
	memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}

#ifndef ASM_MD5

/* The four core functions - F1 is optimized somewhat */

/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))

/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )

/*
 * The core of the MD5 algorithm, this alters an existing MD5 hash to
 * reflect the addition of 16 longwords of new data.  MD5Update blocks
 * the data and converts bytes into longwords for this routine.
 */
void MD5Transform(uint32 buf[4], uint32 const in[16]) {
	register uint32 a, b, c, d;

	a = buf[0];
	b = buf[1];
	c = buf[2];
	d = buf[3];

	MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
	MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
	MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
	MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
	MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
	MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
	MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
	MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
	MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
	MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);

	MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
	MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
	MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
	MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
	MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
	MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
	MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
	MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
	MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
	MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);

	MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
	MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
	MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
	MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
	MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
	MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
	MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
	MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
	MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
	MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);

	MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
	MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
	MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
	MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
	MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
	MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
	MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
	MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
	MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
	MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);

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

/*
 * get MD5 of a byte buffer
 */
int getBytesMD5(const unsigned char* src, unsigned int length, char* md5) {
	unsigned char i = 0;
	unsigned char md5Bytes[16] = { 0 };
	MD5_CTX context;
	if (src == NULL || md5 == NULL)
	{
		return -1;
	}
	MD5Init(&context);
	MD5Update(&context, src, length);
	MD5Final(md5Bytes, &context);
	for (i = 0; i < 16; i++) {
		sprintf(md5, "%02X", md5Bytes[i]);
		md5 += 2;
	}
	*md5 = '\0';
	return 0;
}

/*
 * get MD5 for a string
 */
int getStringMD5(const char* src, char* md5) {
	return getBytesMD5((unsigned char*) src, strlen((char*) src), md5);
}

/**
 * get MD5 of a file
 */
int getFileMD5(const char* path, char* md5) {
	FILE* fp = NULL;
	unsigned char buffer[MD5_FILE_BUFFER_LEN] = { 0 };
	int count = 0;
	MD5_CTX context;
	unsigned char md5Bytes[16] = { 0 };
	int i;
	if (path == NULL || md5 == NULL) {
		return -1;
	}
	fp = fopen(path, "rb");
	if (fp == NULL) {
		return -1;
	}
	MD5Init(&context);
	while ((count = fread(buffer, 1, MD5_FILE_BUFFER_LEN, fp)) > 0) {
		MD5Update(&context, buffer, count);
	}
	MD5Final(md5Bytes, &context);
	for (i = 0; i < 16; i++) {
		sprintf(md5, "%02X", md5Bytes[i]);
		md5 += 2;
	}
	*md5 = '\0';
	return 0;
}

#endif

 下面是调用函数计算MD5的代码:

main.c

 

/*
 * main.c
 *
 *  Created on: 2014-11-6
 *      Author: HZY
 */


#include <stdio.h>
#include <string.h>

#include "md5.h"

int main(int c, char** v){
	char buffer[128];
	getStringMD5("hello world", buffer);
	printf("%s\n", buffer);
	getFileMD5("hello.pdf", buffer);
	printf("%s\n", buffer);
	return 0;
}

 计算无误:



 

如果使用java的话也比较简单,java做了相应的封装:

MD5Test.java

 

package com.hu.md5;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		MD5Test test = new MD5Test();
		System.out.println(test.getStringMD5("hello world"));
		System.out.println(test.getFileMD5("hello.pdf"));
	}

	/**
	 * Get MD5 of a string
	 * 
	 * @param src
	 * @return
	 */
	private String getStringMD5(String src) {
		MessageDigest messageDigest = null;
		byte[] srcBytes = src.getBytes();
		try {
			messageDigest = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		messageDigest.update(srcBytes, 0, srcBytes.length);
		BigInteger bigInt = new BigInteger(1, messageDigest.digest());
		return bigInt.toString(16);
	}

	/**
	 * get MD5 of a file
	 * 
	 * @param file
	 * @return
	 */
	private String getFileMD5(File file) { // 获取文件的MD5值
		MessageDigest messageDigest = null;
		FileInputStream fileInStream = null;
		byte buffer[] = new byte[1024];
		int length = -1;
		try {
			messageDigest = MessageDigest.getInstance("MD5");
			fileInStream = new FileInputStream(file);
			while ((length = fileInStream.read(buffer, 0, 1024)) != -1) {
				messageDigest.update(buffer, 0, length);
			}
			fileInStream.close();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		BigInteger bigInt = new BigInteger(1, messageDigest.digest());
		return bigInt.toString(16);
	}

	/**
	 * get MD5 of a file with file path
	 * 
	 * @param path
	 * @return
	 */
	private String getFileMD5(String path) {
		return getFileMD5(new File(path));
	}

}

 附件有相应的代码。

  • 大小: 24.9 KB
分享到:
评论

相关推荐

    HMAC-MD5实现代码

    Hmac_MD5是一种结合了哈希...同时,由于使用了密钥,Hmac_MD5还能够实现消息的保密性,确保只有持有正确密钥的接收者才能验证消息的完整性。因此,Hmac_MD5算法在网络通信、电子支付、数据加密等领域得到了广泛应用。

    详解Python3之数据指纹MD5校验与对比

    MD5校验码通过散列函数计算而成,可以生成任何数据的数据“指纹”,即我们可以利用MD5将消息或者数据压缩成摘要,是的数据量变小,便于比较验证数据的完整和正确性。因为两个不同的文件几乎不可能拥有相同的MD5哈希...

    文件hash值校验工具

    Hash md5校验工具在论坛上、软件发布时经常用,是为了保证文件的正确性,防止一些人盗用程序,加些木马或者篡改版权,设计的一套验证系统。每个文件都可以用Hash MD5验证程序算出一个固定的MD5码来。软件作者往往会...

    物联网安全_实验9 信息保密性、完整性和不可抵赖性的综合应用.doc

    数字签名 DSS/SHA-1、RSA/MD5 采用SHA-1或MD5消息摘要算法计算消息的摘要值(散列码),用发送者的私钥按DSS或RSA算法加密消息摘要 压缩 PKZIP 消息在传送和存储时可使用PKZIP压缩 E-mail兼容性 Radix-64 对E-mail...

    rar压缩软件.rar

    如果你要解压完整路径名,请使用 'x' 命令。 例子: rar e -or html.rar *.css css\ 从 html.rar 压缩文件中解压所有 *.css 文件到 css 文件夹,不包括存 档的路径。多个文件有相同的名称时自动重命名解压的...

    黄淮学院\考试题\2010-2011

    C、MD5数字签名 D、MD5加密 下面___B____属于对称加密算法。 A、数字签名 B、序列算法 C、RSA算法 D、数字水印 数字签名技术是公开密钥算法的一个典型应用,在发送端,采用__B_____对要发送的信息进行数字签名。 ...

    java开源包7

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

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

    2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...

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

    2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户...

    java开源包5

    用来计算 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开源包8

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

    java开源包1

    用来计算 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框架,目前其最好的性能为在采用...

Global site tag (gtag.js) - Google Analytics