MD5 加密源码(C语言)

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

#define N 1024
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))

#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + ac; (a) = ROL ((a), (s)); (a) += (b); }
#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + ac; (a) = ROL ((a), (s)); (a) += (b); }
#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + ac; (a) = ROL ((a), (s)); (a) += (b); }
#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + ac; (a) = ROL ((a), (s)); (a) += (b); }

typedef unsigned char UINT8;
typedef unsigned int UINT32;

UINT32 s[64] = {
		7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 
		5, 9,  14, 20, 5, 9,  14, 20, 5, 9,  14, 20, 5, 9,  14, 20, 
		4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 
		6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21},

	t[64] = {
		0Xd76aa478, 0Xe8c7b756, 0X242070db, 0Xc1bdceee,
		0Xf57c0faf, 0X4787c62a, 0Xa8304613, 0Xfd469501,
		0X698098d8, 0X8b44f7af, 0Xffff5bb1, 0X895cd7be,
		0X6b901122, 0Xfd987193, 0Xa679438e, 0X49b40821,
		0Xf61e2562, 0Xc040b340, 0X265e5a51, 0Xe9b6c7aa,
		0Xd62f105d, 0X2441453, 0Xd8a1e681, 0Xe7d3fbc8,
		0X21e1cde6, 0Xc33707d6, 0Xf4d50d87, 0X455a14ed,
		0Xa9e3e905, 0Xfcefa3f8, 0X676f02d9, 0X8d2a4c8a,
		0Xfffa3942, 0X8771f681, 0X6d9d6122, 0Xfde5380c,
		0Xa4beea44, 0X4bdecfa9, 0Xf6bb4b60, 0Xbebfbc70,
		0X289b7ec6, 0Xeaa127fa, 0Xd4ef3085, 0x4881d05,
               0Xd9d4d039, 0Xe6db99e5, 0X1fa27cf8, 0Xc4ac5665,
		0Xf4292244, 0X432aff97, 0Xab9423a7, 0Xfc93a039,
		0X655b59c3, 0X8f0ccc92, 0Xffeff47d, 0X85845dd1,
		0X6fa87e4f, 0Xfe2ce6e0, 0Xa3014314, 0X4e0811a1,
		0Xf7537e82, 0Xbd3af235, 0X2ad7d2bb, 0Xeb86d391},

	Index[64] = {
	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
	1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,
	5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
	0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9},

	INIT[4] = {
		0x67452301,
		0xefcdab89,
		0x98badcfe,
		0x10325476};


  //
 //            工具函数                  //
//
FILE *open(UINT8 *filename, UINT8 *mode)	       //打开文件
{
	FILE *fp = NULL;
	if((fp = fopen(filename, mode)) == NULL)
	{
		printf("file open error!\n");
		exit(-1);
	}
	return fp;
}

void close(FILE *fp)        //关闭文件
{
	while(fclose(fp));
}
/*将整型数据转换成字符串数据*/
void encode(UINT32 *input, UINT8 *output, UINT32 len)
{
	UINT32 i, j; 

	for(i = 0, j = 0; i < len; i += 4, j++)
	{
		output[i]     = (UINT8)(input[j] & 0Xff);
		output[i + 1] = (UINT8)((input[j] >> 8 ) & 0Xff);
		output[i + 2] = (UINT8)((input[j] >> 16) & 0Xff);
		output[i + 3] = (UINT8)((input[j] >> 24) & 0Xff);
	}
}

/*将字符串转换成整型数据*/
void decode(UINT8 * input, UINT32 * output, UINT32 len)
{
	UINT32 i = 0,
		j = 0;
	for(; i < len; i += 4, j++)
		output[j] = (UINT32)input[i] | (((UINT32)input[i + 1])<<8) |
		(((UINT32)input[i + 2])<<16) | (((UINT32)input[i + 3])<<24);
}

  //
 //            功能函数                  //
//

/*初始化链块变量*/
void init_md5()
{
	INIT[0] = 0x67452301;
	INIT[1] = 0xefcdab89;
	INIT[2] = 0x98badcfe;
	INIT[3] = 0x10325476;
}

/*数字签名计算*/
void digest_opt(UINT8 *m, UINT32 len)
{
	UINT32 i = 0, j = 0, k = 0, temp[4], date[16];

	for(i = 0; i < 4; i++)
	  temp[i] = INIT[i];

    /*对多个数据快进行签名运算*/
	for(; len > 0; len -= 64, j += 4)
	{
		/*将64字节的字符串转换成16个整型数据*/
		decode(m+j, date, 64);

		for(i = 0; i < 64; i++, k = (k+4-1)%4)
		{
			switch(i/16)
			{
				case 0: FF(temp[k%4], temp[(k+1)%4], temp[(k+2)%4], temp[(k+3)%4], date[Index[i]], s[i], t[i]); break;
				case 1: GG(temp[k%4], temp[(k+1)%4], temp[(k+2)%4], temp[(k+3)%4], date[Index[i]], s[i], t[i]); break;
				case 2: HH(temp[k%4], temp[(k+1)%4], temp[(k+2)%4], temp[(k+3)%4], date[Index[i]], s[i], t[i]); break;
				case 3: II(temp[k%4], temp[(k+1)%4], temp[(k+2)%4], temp[(k+3)%4], date[Index[i]], s[i], t[i]); break;
				default: break;
			}
		}
	}

	for(i = 0; i < 4; i++)
	  INIT[i] += temp[i];
}
/*计算需要填充的字节长度*/
UINT32 pad_len(UINT32 len)
{
	UINT32 mod;
	mod = len%64;
	/*p_len 为填充字节数计算*/
	if(mod <= 56)
	  len =  64 - mod;
	else
	  len = 128 - mod;
    return len;
}

/*计算原消息长度的填充信息*/
void len_data(UINT8 * msgLen, const UINT32 len)
{
	UINT32 bufLen[2];
	/*计算数据长度的填充数据*/
	bufLen[0] = len << 3;
	bufLen[1] = len >> 29;
	encode(bufLen, msgLen, 8);
}

/*字节填充*/
UINT8 * tail_pad(UINT8 * msg, UINT8 *msgLen, const UINT32 len, const UINT32 padLen)
{
	UINT8 *buf = NULL; 

	/*根据填充字节数构建新串*/
	buf = (UINT8 *)calloc(sizeof(UINT8), len + padLen);
	/*初始化新串的值*/
	memcpy(buf, msg, len);
	buf[len] = 0X80;							//若buf[len]为带符号字符型, 赋值后将变成负数
	memcpy(buf + len + padLen - 8, msgLen, 8);
	return buf;
}
/*对需要填充的消息进行数字签名*/
void md5_tail(UINT8 *msg, UINT8 *digest,const UINT32 len, UINT8 *msgLen)
{
	UINT32 padLen, i;
	UINT8  *buf = NULL;

	padLen = pad_len(len);
	buf    = tail_pad(msg, msgLen, len, padLen);//填充字符串, 得到新串buf
	digest_opt(buf, len + padLen);              //数字签名计算

	encode(INIT, digest, 16);                   //存储最终结果
	free(buf);
}

/*对消息进行数字签名*/
void md5_msg(UINT8 *msg, UINT8 *digest)
{
	UINT32 len = strlen(msg);                   //len为当前消息长度
	UINT8 msgLen[8];

	init_md5();
    len_data(msgLen, len);                      //计算填充的长度信息
	md5_tail(msg, digest, len, msgLen);         //摘要计算
}

/*对文件进行数字签名*/
void md5_file(FILE *fp, UINT8 *digest)
{
	UINT32 bufLen  = 0,
		   fileLen = 0;
	UINT8  buf[N], msgLen[8];

	init_md5();
	bufLen = fread(buf, sizeof(UINT8), N, fp);
	fileLen += bufLen;
	while(!feof(fp))
	{
        digest_opt(buf, N);
        bufLen = fread(buf, sizeof(UINT8), N, fp);
		fileLen += bufLen;
	}
    len_data(msgLen, fileLen - 1);              //计算填充的长度信息
	md5_tail(buf, digest, bufLen - 1, msgLen);  //摘要计算
}

/*主测试函数*/
int main()
{
	FILE * fp;
	UINT8 digest[16];
	UINT32 i;
	fp = open("m", "r");
	md5_file(fp, digest);
    close(fp);
	printf("file\tdigest: ");
	for(i = 0; i < 16; i++)
	    printf("%02x", digest[i]);
	printf("\n");
	
	md5_msg("abc", digest);
	printf("message\tdigest: ");
	for(i = 0; i < 16; i++)
	    printf("%02x", digest[i]);
	printf("\n");
	return 0;
}

 

转载于:https://my.oschina.net/Kuture/blog/702279

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值