您的位置:首页 > 编程语言 > C语言/C++

MD5 加密源码(C语言)

2016-06-28 00:00 423 查看
摘要: MD5 加密源码

#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[
7fe0
(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
, 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息