现在的位置: 首页 > 综合 > 正文

计算文件MD5(含MD5算法)

2014年01月28日 ⁄ 综合 ⁄ 共 4073字 ⁄ 字号 评论关闭
#include <stdio.h>
#include <stdlib.h>

#define A	(0x67452301)
#define B	(0xefcdab89)
#define C	(0x98badcfe)
#define D	(0x10325476)

#define X(_a, _b, _r, _m, _s, _t) \
	((_a) = (_b) + rol((_a) + (_r) + (_m) + (_t), (_s)))

const int N[4][2] = {{0, 1}, {1, 5}, {5, 3}, {0, 7}};

const unsigned long S[4][4] = {
	{7, 12, 17, 22},
	{5, 9, 14, 20},
	{4, 11, 16, 23},
	{6, 10, 15, 21}
};

//(4294967296 * abs(sin(i *16 + j + 1)))
const unsigned long T[4][16] = {
	{
		0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
		0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821
	}, {
		0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
		0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a
	}, {
		0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
		0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665
	}, {
		0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
		0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
	}
};

//DESP: MD5 F
unsigned long F(unsigned long x, unsigned long y, unsigned long z)
{
	return (x & y) | ((~x) & z);
}

//DESP: MD5 G
unsigned long G(unsigned long x, unsigned long y, unsigned long z)
{
	return (x & z) | (y & (~z));
}

//DESP: MD5 H
unsigned long H(unsigned long x, unsigned long y, unsigned long z)
{
	return (x ^ y ^ z);
}

//DESP: MD5 I
unsigned long I(unsigned long x, unsigned long y, unsigned long z)
{
	return y ^ (x | (~z));
}

//non-line function
unsigned long ((*md5nl[4])(unsigned long x, unsigned long y, unsigned long z)) = {
	F, G, H, I
};

//DESP: Rotate Left
unsigned long rol(unsigned long n, unsigned long c)
{
	return (n << c) | (n >> (32 - c));
}

//DESP: MD5 update
void md5_update(unsigned long chain[4], unsigned long msg[16])
{
	unsigned long state[4];
	int i, j, n, k;

	//DO: copy state
	for(i = 0; i < 4; i++)
		state[i] = chain[i];

	for(i = 0; i < 4; i++) {
		n = N[i][0];
		
		for(j = 0; j < 16; j++) {
			k = ((4 - (j & 3)) & 3);

			//DO: md5 FF,GG,HH,II
			X(state[k],
				state[(k + 1) & 3],
				md5nl[i](state[(k + 1) & 3], state[(k + 2) & 3], state[(k + 3) & 3]),
				msg[n & 0x0f],
				S[i][j & 3],
				T[i][j]);

			n += N[i][1];
		}
	}

	//DO: add to chain
	for(i = 0; i < 4; i++)
		chain[i] += state[i];

	return;
}

//DESP: MD5 final
void md5_final(unsigned long chain[4], unsigned char *tail, unsigned long len[2])
{
	unsigned char msg[128];
	int i, l, n;

	//tail length
	l = len[0] & 0x3f;

	//buffer size
	n = (l >= 56)? 120: 56;

	//copy tail to buffer
	for(i = 0; i < l; i++)
		msg[i] = tail[i];
	
	if(n > l) {
		//DO: fill message
		msg[l] = 0x80;
		
		for(i = l + 1; i < n; i++)
			msg[i] = 0;

	}

	//append bits length to message
	((unsigned long *)(msg + n))[0] = len[0] << 3;
	((unsigned long *)(msg + n))[1] = len[1] << 3 | len[0] >> 29;
	md5_update(chain, (unsigned long *)msg);

	if(n == 120)
		md5_update(chain, (unsigned long *)&msg[64]);

	return;
}

//DESP: MD5 initialize chaining variables
void md5_init(unsigned long chain[4])
{
	chain[0] = A;
	chain[1] = B;
	chain[2] = C;
	chain[3] = D;
	return;
}

#define BLOCK_SIZE	(0x1000 * sizeof(unsigned char))
#define BLOCK_DWORD	(BLOCK_SIZE / sizeof(unsigned long))
#define MSG_SIZE	(0x40 * sizeof(unsigned char))
#define MSG_DWORD	(MSG_SIZE / sizeof(unsigned long))

//DESP: update chain for echo 4kb
void md5_file_block(unsigned long sum[4], unsigned long block[BLOCK_DWORD])
{
	int i;

	for(i = 0; i < BLOCK_DWORD; i += MSG_DWORD)
		md5_update(sum, &block[i]);

	return;
}

//DESP: final chain
void md5_file_final(unsigned long sum[4], unsigned long *block, unsigned long len[2])
{
	int i, n;

	//count of block
	n = (len[0] % BLOCK_SIZE) / MSG_SIZE;

	//reserve
	if((len[0] % MSG_SIZE) == 0)
		n--;

	n *= MSG_DWORD;

	for(i = 0; i < n; i += MSG_DWORD)
		md5_update(sum, &block[i]);

	md5_final(sum, (unsigned char *)&block[i], len);
	return;
}

//DESP: demo for compute file's MD5
int md5_file(char *file, unsigned char result[16])
{
	FILE *in;
	int r;
	unsigned long n;
	unsigned long *p;
	unsigned long l[2];
	unsigned long sum[4];
	
	//open file
	if(fopen_s(&in, file, "rb") != 0)
		return 0;
	
	l[0] = l[1] = 0;
	p = (unsigned long *)malloc(BLOCK_SIZE);
	
	if(!p) {
		fclose(in);
		return 0;
	}
	
	r = 1;
	md5_init(sum);
	
	for(;;) {
		n = fread(p, sizeof(unsigned char), BLOCK_SIZE, in);
		
		if(ferror(in)) {
			r = 0;
			break;
		}
		
		if(feof(in)) {
			n += l[0];
			
			if(n < l[0])
				l[1]++;
			
			md5_final(sum, (unsigned char *)p, l);
			
			for(n = 0; n < 4; n++)
				((unsigned long *)result)[n] = sum[n];
			
			break;
		} else {
			md5_file_block(sum, p);
			n += l[0];
			
			if(n < l[0])
				l[1]++;
		}

	}
	
	free(p);
	fclose(in);
	return r;
}

int main(int argc, char *argv[])
{
	int i;
	unsigned char sum[16];

	if(argc == 2) {
		
		if(!md5_file(argv[1], sum))
			return 1;

		for(i = 0; i < 16; i++)
			printf("%02x", sum[i]);
		
		putchar(' ');
		puts(argv[1]);
		return 0;
	}

	return 1;
}

抱歉!评论已关闭.