MD5算法实现
什么是MD5???---MD5的全称是Message-Digest Algorithm 5
MD5的典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止被篡改。比如,在UNIX下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如:
MD5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461
这就是tanajiya.tar.gz文件的数字签名。MD5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的MD5信息摘要。如果在以后传播这个文件的过程中,无论文件的内容发生了任何形式的改变(包括人为修改或者下载过程中线路不稳定引起的传输错误等),只要你对这个文件重新计算MD5时就会发现信息摘要不相同,由此可以确定你得到的只是一个不正确的文件。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的 "抵赖",这就是所谓的数字签名应用。
MD5还广泛用于加密和解密技术上。比如在UNIX系统中用户的密码就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。
/*
md5.c
this is for encryt by md5,just simple implement it.
注释:可以使用,和百度百科的最后结果相同
来源:http://www.linuxidc.com/Linux/2012-07/65941.htm
时间:2014.12.19
原理:1填充:将数据填充为N*512+448(即N*64+56)
2算法计算,将 A->a,a经FF,GG,HH,II计算,A=A+a
3将计算后的各块级联生成128位的加密算法
*/
#include <stdio.h>
#include <string.h>
//#include "md5.h" 头文件已经加到程序中
#ifndef MD5_FORENCRPTY_H
#define MD5_FORENCRPTY_H
/*this is only 32bit*/
typedef unsigned int md5_int;
struct MD5_struct
{
md5_int A;
md5_int B;
md5_int C;
md5_int D;
md5_int lenbuf;
char buffer[128];
};
void md5_init(struct MD5_struct *ctx,char * buffer);
void md5_process(struct MD5_struct * ctx);
char * md5_fini(struct MD5_struct *ctx,void *rebuf);
void md5_buffer_full(struct MD5_struct * ctx);
void md5_print(struct MD5_struct * ctx);
#endif
struct MD5_struct ctx;
/*
extern void md5_init(struct MD5_struct *ctx,char * buffer);
extern void md5_process(struct MD5_struct * ctx);
extern char * md5_fini(struct MD5_struct *ctx,void * rebuf);
extern void md5_buffer_full(struct MD5_struct * ctx);
extern void md5_print(struct MD5_struct * ctx);
*/
/* set data for fill buffer */
md5_int fullbuffer[64]={0x80,0};
md5_int M[16]={0,0};
/*
for loop A\B\C\D ways
*/
#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 ROT(x,s) (x=(x<<s)|(x>>(32-s)))
#define FF(a,b,c,d,j,s,T) {a=a+(F(b,c,d)+M[j]+T);ROT(a,s);a=a+b;}
#define GG(a,b,c,d,j,s,T) {a=a+(G(b,c,d)+M[j]+T);ROT(a,s);a=a+b;}
#define HH(a,b,c,d,j,s,T) {a=a+(H(b,c,d)+M[j]+T);ROT(a,s);a=a+b;}
#define II(a,b,c,d,j,s,T) {a=a+(I(b,c,d)+M[j]+T);ROT(a,s);a=a+b;}
/*
init MD5_struct ctx
*/
void md5_init(struct MD5_struct *ctx,char * buffer)
{
ctx->A=0x67452301;//一个四个字的缓冲器(A,B,C,D)来计算报文摘要
ctx->B=0xefcdab89;
ctx->C=0x98badcfe;
ctx->D=0x10325476;
ctx->lenbuf=strlen(buffer);
memcpy(ctx->buffer,buffer,ctx->lenbuf);
//memcpy(void*dest,constvoid*src,size_tcount)
}
/*
print ctx's message
*/
void md5_print(struct MD5_struct *ctx)
{
printf("******************************\n");
printf("ctx->A:%x\n",ctx->A);
printf("ctx->B:%x\n",ctx->B);
printf("ctx->C:%x\n",ctx->C);
printf("ctx->D:%x\n",ctx->D);
printf("ctx->lenbuf:%d\n",ctx->lenbuf);
printf("ctx->buffer:%s\n",ctx->buffer);
printf("\n\r************print******************\n");
}
/*
fill buffer to mod%64
*/
void md5_buffer_full(struct MD5_struct *ctx)
{
md5_int sizebyte[2]={0,0};
md5_int len=ctx->lenbuf;
md5_int byte=len>56?(64-(len-56)):56-len;
memcpy(&ctx->buffer[len],fullbuffer,byte);
sizebyte[0]+=(ctx->lenbuf<<3);
if(sizebyte[0]<ctx->lenbuf)
sizebyte[1]++;
memcpy(&ctx->buffer[len+byte],&sizebyte,sizeof(sizebyte));
}
/*
deal message
*/
void md5_process(struct MD5_struct *ctx)
{
int i=0;
int j;
md5_int a=ctx->A;
md5_int b=ctx->B;
md5_int c=ctx->C;
md5_int d=ctx->D;
for(i=0;i<=ctx->lenbuf;i+=64)//loop time
{
memcpy(M,ctx->buffer,sizeof(md5_int)*16);
/* round 1 */
FF(a,b,c,d, 0, 7,0xd76aa478);
FF(d,a,b,c, 1,12,0xe8c7b756);
FF(c,d,a,b, 2,17,0x242070db);
FF(b,c,d,a, 3,22,0xc1bdceee);
FF(a,b,c,d, 4, 7,0xf57c0faf);
FF(d,a,b,c, 5,12,0x4787c62a);
FF(c,d,a,b, 6,17,0xa8304613);
FF(b,c,d,a, 7,22,0xfd469501);
FF(a,b,c,d, 8, 7,0x698098d8);
FF(d,a,b,c, 9,12,0x8b44f7af);
FF(c,d,a,b,10,17,0xffff5bb1);
FF(b,c,d,a,11,22,0x895cd7be);
FF(a,b,c,d,12, 7,0x6b901122);
FF(d,a,b,c,13,12,0xfd987193);
FF(c,d,a,b,14,17,0xa679438e);
FF(b,c,d,a,15,22,0x49b40821);
/* round 2 */
GG(a,b,c,d, 1, 5,0xf61e2562);
GG(d,a,b,c, 6, 9,0xc040b340);
GG(c,d,a,b,11,14,0x265e5a51);
GG(b,c,d,a, 0,20,0xe9b6c7aa);
GG(a,b,c,d, 5, 5,0xd62f105d);
GG(d,a,b,c,10, 9,0x02441453);
GG(c,d,a,b,15,14,0xd8a1e681);
GG(b,c,d,a, 4,20,0xe7d3fbc8);
GG(a,b,c,d, 9, 5,0x21e1cde6);
GG(d,a,b,c,14, 9,0xc33707d6);
GG(c,d,a,b, 3,14,0xf4d50d87);
GG(b,c,d,a, 8,20,0x455a14ed);
GG(a,b,c,d,13, 5,0xa9e3e905);
GG(d,a,b,c, 2, 9,0xfcefa3f8);
GG(c,d,a,b, 7,14,0x676f02d9);
GG(b,c,d,a,12,20,0x8d2a4c8a);
/* round 3 */
HH(a,b,c,d, 5, 4,0xfffa3942);
HH(d,a,b,c, 8,11,0x8771f681);
HH(c,d,a,b,11,16,0x6d9d6122);
HH(b,c,d,a,14,23,0xfde5380c);
HH(a,b,c,d, 1, 4,0xa4beea44);
HH(d,a,b,c, 4,11,0x4bdecfa9);
HH(c,d,a,b, 7,16,0xf6bb4b60);
HH(b,c,d,a,10,23,0xbebfbc70);
HH(a,b,c,d,13, 4,0x289b7ec6);
HH(d,a,b,c, 0,11,0xeaa127fa);
HH(c,d,a,b, 3,16,0xd4ef3085);
HH(b,c,d,a, 6,23,0x04881d05);
HH(a,b,c,d, 9, 4,0xd9d4d039);
HH(d,a,b,c,12,11,0xe6db99e5);
HH(c,d,a,b,15,16,0x1fa27cf8);
HH(b,c,d,a, 2,23,0xc4ac5665);
/* round 4 */
II(a,b,c,d, 0, 6,0xf4292244);
II(d,a,b,c, 7,10,0x432aff97);
II(c,d,a,b,14,15,0xab9423a7);
II(b,c,d,a, 5,21,0xfc93a039);
II(a,b,c,d,12, 6,0x655b59c3);
II(d,a,b,c, 3,10,0x8f0ccc92);
II(c,d,a,b,10,15,0xffeff47d);
II(b,c,d,a, 1,21,0x85845dd1);
II(a,b,c,d, 8, 6,0x6fa87e4f);
II(d,a,b,c,15,10,0xfe2ce6e0);
II(c,d,a,b, 6,15,0xa3014314);
II(b,c,d,a,13,21,0x4e0811a1);
II(a,b,c,d, 4, 6,0xf7537e82);
II(d,a,b,c,11,10,0xbd3af235);
II(c,d,a,b, 2,15,0x2ad7d2bb);
II(b,c,d,a, 9,21,0xeb86d391);
ctx->A+=a;
ctx->B+=b;
ctx->C+=c;
ctx->D+=d;
}
}
/*
store result
*/
char * md5_fini(struct MD5_struct *ctx,void *rebuf)
{
int i=0;
memset(rebuf,0,16);
memcpy(&((unsigned char *)rebuf)[0],&ctx->A,sizeof(ctx->A));
memcpy(&((unsigned char *)rebuf)[4],&ctx->B,sizeof(ctx->B));
memcpy(&((unsigned char *)rebuf)[8],&ctx->C,sizeof(ctx->C));
memcpy(&((unsigned char *)rebuf)[12],&ctx->D,sizeof(ctx->D));
/* print md5 result */
md5_print(ctx);
printf("md5:");
while(i<16)
{
printf("%02x",((unsigned char *)rebuf)[i++]);
}
printf("\n*****nj****************************\n");
return rebuf;
}
int main(int argc,char ** argv)
{
unsigned char rebuf[16];
unsigned char message[64];
printf("please enter you message for encrypt:");
scanf("%s",message);
md5_init(&ctx,message);
md5_buffer_full(&ctx);
md5_process(&ctx);
md5_fini(&ctx,rebuf);
return 0;
}