搜档网
当前位置:搜档网 › MD5算法实现

MD5算法实现

MD5算法实现
MD5算法实现

md5加密算法c实现

md5的介绍的文章网上很多,关于md5的来历,用途什么的这里就不再介绍了。这里主要介绍代码。代码明白了就什么都明白了。

////////////////////////////////////////////////////////////////////

/*md5.h*/

#ifndef_MD5_H_

#define_MD5_H_

#defineR_memset(x,y,z)memset(x,y,z)

#defineR_memcpy(x,y,z)memcpy(x,y,z)

#defineR_memcmp(x,y,z)memcmp(x,y,z)

typedefunsignedlongUINT4;

typedefunsignedchar*POINTER;

/*MD5context.*/

typedefstruct{

/*state(ABCD)*/

/*四个32bits数,用于存放最终计算得到的消息摘要。当消息长度〉512bits时,也用于存放每个512bits的中间结果*/

UINT4state[4];

/*numberofbits,modulo2^64(lsbfirst)*/

/*存储原始信息的bits数长度,不包括填充的bits,最长为2^64bits,因为2^64是一个64位数的最大值*/

UINT4count[2];

/*inputbuffer*/

/*存放输入的信息的缓冲区,512bits*/

unsignedcharbuffer[64];

}MD5_CTX;

voidMD5Init(MD5_CTX*);

voidMD5Update(MD5_CTX*,unsignedchar*,unsignedint);

voidMD5Final(unsignedchar[16],MD5_CTX*);

#endif/*_MD5_H_*/

///////////////////////////////////////////////////////////////////////////

/*md5.cpp*/

#include"stdafx.h"

/*ConstantsforMD5Transformroutine.*/

/*md5转换用到的常量,算法本身规定的*/

#defineS117

#defineS1212

#defineS1317

#defineS1422

#defineS215

#defineS229

#defineS2314

#defineS2420

#defineS314

#defineS3211

#defineS3316

#defineS3423

#defineS416

#defineS4210

#defineS4315

#defineS4421

staticvoidMD5Transform(UINT4[4],unsignedchar[64]);

staticvoidEncode(unsignedchar*,UINT4*,unsignedint);

staticvoidDecode(UINT4*,unsignedchar*,unsignedint);

/*

用于bits填充的缓冲区,为什么要64个字节呢?因为当欲加密的信息的bits数被512除其余数为448时,

需要填充的bits的最大值为512=64*8。

*/

staticunsignedcharPADDING[64]={

0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

};

/*

接下来的这几个宏定义是md5算法规定的,就是对信息进行md5加密都要做的运算。

据说有经验的高手跟踪程序时根据这几个特殊的操作就可以断定是不是用的md5

*/

/*F,G,HandIarebasicMD5functions.

*/

#defineF(x,y,z)(((x)&(y))|((~x)&(z)))

#defineG(x,y,z)(((x)&(z))|((y)&(~z)))

#defineH(x,y,z)((x)^(y)^(z))

#defineI(x,y,z)((y)^((x)|(~z)))

/*ROTA TE_LEFTrotatesxleftnbits.

*/

#defineROTATE_LEFT(x,n)(((x)<<(n))|((x)>>(32-(n))))

/*FF,GG,HH,andIItransformationsforrounds1,2,3,and4. Rotationisseparatefromadditiontopreventrecomputation.

*/

#defineFF(a,b,c,d,x,s,ac){/

(a)+=F((b),(c),(d))+(x)+(UINT4)(ac);/

(a)=ROTATE_LEFT((a),(s));/

(a)+=(b);/

}

#defineGG(a,b,c,d,x,s,ac){/

(a)+=G((b),(c),(d))+(x)+(UINT4)(ac);/

(a)=ROTATE_LEFT((a),(s));/

(a)+=(b);/

}

#defineHH(a,b,c,d,x,s,ac){/

(a)+=H((b),(c),(d))+(x)+(UINT4)(ac);/

(a)=ROTATE_LEFT((a),(s));/

(a)+=(b);/

}

#defineII(a,b,c,d,x,s,ac){/

(a)+=I((b),(c),(d))+(x)+(UINT4)(ac);/

(a)=ROTATE_LEFT((a),(s));/

(a)+=(b);/

}

/*MD5initialization.BeginsanMD5operation,writinganewcontext.*/

/*初始化md5的结构*/

voidMD5Init(MD5_CTX*context)

{

/*将当前的有效信息的长度设成0,这个很简单,还没有有效信息,长度当然是0了*/ context->count[0]=context->count[1]=0;

/*Loadmagicinitializationconstants.*/

/*初始化链接变量,算法要求这样,这个没法解释了*/

context->state[0]=0x67452301;

context->state[1]=0xefcdab89;

context->state[2]=0x98badcfe;

context->state[3]=0x10325476;

}

/*MD5blockupdateoperation.ContinuesanMD5message-digest

operation,processinganothermessageblock,andupdatingthe

context.*/

/*将与加密的信息传递给md5结构,可以多次调用

context:初始化过了的md5结构

input:欲加密的信息,可以任意长

inputLen:指定input的长度

*/

voidMD5Update(MD5_CTX*context,unsignedchar*input,unsignedintinputLen)

{

unsignedinti,index,partLen;

/*Computenumberofbytesmod64*/

/*计算已有信息的bits长度的字节数的模64,64bytes=512bits。

用于判断已有信息加上当前传过来的信息的总长度能不能达到512bits,

如果能够达到则对凑够的512bits进行一次处理*/

index=(unsignedint)((context->count[0]>>3)&0x3F);

/*Updatenumberofbits*//*更新已有信息的bits长度*/

if((context->count[0]+=((UINT4)inputLen<<3))<((UINT4)inputLen<<3))

context->count[1]++;

context->count[1]+=((UINT4)inputLen>>29);

/*计算已有的字节数长度还差多少字节可以凑成64的整倍数*/

partLen=64-index;

/*Transformasmanytimesaspossible.

*/

/*如果当前输入的字节数大于已有字节数长度补足64字节整倍数所差的字节数*/

if(inputLen>=partLen)

{

/*用当前输入的内容把context->buffer的内容补足512bits*/

R_memcpy((POINTER)&context->buffer[index],(POINTER)input,partLen);

/*用基本函数对填充满的512bits(已经保存到context->buffer中)做一次转换,转换结果保存到context->state中*/

MD5Transform(context->state,context->buffer);

/*

对当前输入的剩余字节做转换(如果剩余的字节<在输入的input缓冲区中>大于512bits的

话),

转换结果保存到context->state中

*/

for(i=partLen;i+63

MD5Transform(context->state,&input[i]);

index=0;

}

else

i=0;

/*Bufferremaininginput*/

/*将输入缓冲区中的不足填充满512bits的剩余内容填充到context->buffer中,留待以后再作处理*/

R_memcpy((POINTER)&context->buffer[index],(POINTER)&input[i],inputLen-i);

}

/*MD5finalization.EndsanMD5message-digestoperation,writingthe themessagedigestandzeroizingthecontext.*/

/*获取加密的最终结果

digest:保存最终的加密串

context:你前面初始化并填入了信息的md5结构

*/

voidMD5Final(unsignedchardigest[16],MD5_CTX*context)

{

unsignedcharbits[8];

unsignedintindex,padLen;

/*Savenumberofbits*/

/*将要被转换的信息(所有的)的bits长度拷贝到bits中*/

Encode(bits,context->count,8);

/*Padoutto56mod64.*/

/*计算所有的bits长度的字节数的模64,64bytes=512bits*/

index=(unsignedint)((context->count[0]>>3)&0x3f);

/*计算需要填充的字节数,padLen的取值范围在1-64之间*/

padLen=(index<56)?(56-index):(120-index);

/*这一次函数调用绝对不会再导致MD5Transform的被调用,因为这一次不会填满512bits*/ MD5Update(context,PADDING,padLen);

/*Appendlength(beforepadding)*/

/*补上原始信息的bits长度(bits长度固定的用64bits表示),这一次能够恰巧凑够512bits,不会多也不会少*/

MD5Update(context,bits,8);

/*Storestateindigest*/

/*将最终的结果保存到digest中。ok,终于大功告成了*/

Encode(digest,context->state,16);

/*Zeroizesensitiveinformation.*/

R_memset((POINTER)context,0,sizeof(*context));

}

/*MD5basictransformation.Transformsstatebasedonblock.*/

/*

对512bits信息(即block缓冲区)进行一次处理,每次处理包括四轮

state[4]:md5结构中的state[4],用于保存对512bits信息加密的中间结果或者最终结果block[64]:欲加密的512bits信息

*/

staticvoidMD5Transform(UINT4state[4],unsignedcharblock[64])

{

UINT4a=state[0],b=state[1],c=state[2],d=state[3],x[16];

Decode(x,block,64);

/*Round1*/

FF(a,b,c,d,x[0],S11,0xd76aa478);/*1*/

FF(d,a,b,c,x[1],S12,0xe8c7b756);/*2*/

FF(c,d,a,b,x[2],S13,0x242070db);/*3*/

FF(b,c,d,a,x[3],S14,0xc1bdceee);/*4*/

FF(a,b,c,d,x[4],S11,0xf57c0faf);/*5*/

FF(d,a,b,c,x[5],S12,0x4787c62a);/*6*/

FF(c,d,a,b,x[6],S13,0xa8304613);/*7*/

FF(b,c,d,a,x[7],S14,0xfd469501);/*8*/

FF(a,b,c,d,x[8],S11,0x698098d8);/*9*/

FF(d,a,b,c,x[9],S12,0x8b44f7af);/*10*/

FF(c,d,a,b,x[10],S13,0xffff5bb1);/*11*/

FF(b,c,d,a,x[11],S14,0x895cd7be);/*12*/

FF(a,b,c,d,x[12],S11,0x6b901122);/*13*/

FF(d,a,b,c,x[13],S12,0xfd987193);/*14*/

FF(c,d,a,b,x[14],S13,0xa679438e);/*15*/

FF(b,c,d,a,x[15],S14,0x49b40821);/*16*/

/*Round2*/

GG(a,b,c,d,x[1],S21,0xf61e2562);/*17*/

GG(d,a,b,c,x[6],S22,0xc040b340);/*18*/

GG(c,d,a,b,x[11],S23,0x265e5a51);/*19*/

GG(a,b,c,d,x[5],S21,0xd62f105d);/*21*/ GG(d,a,b,c,x[10],S22,0x2441453);/*22*/ GG(c,d,a,b,x[15],S23,0xd8a1e681);/*23*/ GG(b,c,d,a,x[4],S24,0xe7d3fbc8);/*24*/ GG(a,b,c,d,x[9],S21,0x21e1cde6);/*25*/ GG(d,a,b,c,x[14],S22,0xc33707d6);/*26*/ GG(c,d,a,b,x[3],S23,0xf4d50d87);/*27*/ GG(b,c,d,a,x[8],S24,0x455a14ed);/*28*/ GG(a,b,c,d,x[13],S21,0xa9e3e905);/*29*/ GG(d,a,b,c,x[2],S22,0xfcefa3f8);/*30*/ GG(c,d,a,b,x[7],S23,0x676f02d9);/*31*/ GG(b,c,d,a,x[12],S24,0x8d2a4c8a);/*32*/

/*Round3*/

HH(a,b,c,d,x[5],S31,0xfffa3942);/*33*/ HH(d,a,b,c,x[8],S32,0x8771f681);/*34*/ HH(c,d,a,b,x[11],S33,0x6d9d6122);/*35*/ HH(b,c,d,a,x[14],S34,0xfde5380c);/*36*/ HH(a,b,c,d,x[1],S31,0xa4beea44);/*37*/ HH(d,a,b,c,x[4],S32,0x4bdecfa9);/*38*/ HH(c,d,a,b,x[7],S33,0xf6bb4b60);/*39*/ HH(b,c,d,a,x[10],S34,0xbebfbc70);/*40*/ HH(a,b,c,d,x[13],S31,0x289b7ec6);/*41*/ HH(d,a,b,c,x[0],S32,0xeaa127fa);/*42*/ HH(c,d,a,b,x[3],S33,0xd4ef3085);/*43*/ HH(b,c,d,a,x[6],S34,0x4881d05);/*44*/ HH(a,b,c,d,x[9],S31,0xd9d4d039);/*45*/ HH(d,a,b,c,x[12],S32,0xe6db99e5);/*46*/ HH(c,d,a,b,x[15],S33,0x1fa27cf8);/*47*/ HH(b,c,d,a,x[2],S34,0xc4ac5665);/*48*/

/*Round4*/

II(a,b,c,d,x[0],S41,0xf4292244);/*49*/

II(d,a,b,c,x[7],S42,0x432aff97);/*50*/

II(c,d,a,b,x[14],S43,0xab9423a7);/*51*/ II(b,c,d,a,x[5],S44,0xfc93a039);/*52*/

II(a,b,c,d,x[12],S41,0x655b59c3);/*53*/ II(d,a,b,c,x[3],S42,0x8f0ccc92);/*54*/

II(c,d,a,b,x[10],S43,0xffeff47d);/*55*/

II(b,c,d,a,x[1],S44,0x85845dd1);/*56*/

II(a,b,c,d,x[8],S41,0x6fa87e4f);/*57*/

II(d,a,b,c,x[15],S42,0xfe2ce6e0);/*58*/

II(c,d,a,b,x[6],S43,0xa3014314);/*59*/

II(a,b,c,d,x[4],S41,0xf7537e82);/*61*/

II(d,a,b,c,x[11],S42,0xbd3af235);/*62*/

II(c,d,a,b,x[2],S43,0x2ad7d2bb);/*63*/

II(b,c,d,a,x[9],S44,0xeb86d391);/*64*/

state[0]+=a;

state[1]+=b;

state[2]+=c;

state[3]+=d;

/*Zeroizesensitiveinformation.*/

R_memset((POINTER)x,0,sizeof(x));

}

/*Encodesinput(UINT4)intooutput(unsignedchar).Assumeslenis

amultipleof4.*/

/*将4字节的整数copy到字符形式的缓冲区中

output:用于输出的字符缓冲区

input:欲转换的四字节的整数形式的数组

len:output缓冲区的长度,要求是4的整数倍

*/

staticvoidEncode(unsignedchar*output,UINT4*input,unsignedintlen)

{

unsignedinti,j;

for(i=0,j=0;j

output[j]=(unsignedchar)(input[i]&0xff);

output[j+1]=(unsignedchar)((input[i]>>8)&0xff);

output[j+2]=(unsignedchar)((input[i]>>16)&0xff);

output[j+3]=(unsignedchar)((input[i]>>24)&0xff);

}

}

/*Decodesinput(unsignedchar)intooutput(UINT4).Assumeslenis

amultipleof4.*/

/*与上面的函数正好相反,这一个把字符形式的缓冲区中的数据copy到4字节的整数中(即以整数形式保存)

output:保存转换出的整数

input:欲转换的字符缓冲区

len:输入的字符缓冲区的长度,要求是4的整数倍

*/

staticvoidDecode(UINT4*output,unsignedchar*input,unsignedintlen)

{

unsignedinti,j;

for(i=0,j=0;j

output[i]=((UINT4)input[j])|(((UINT4)input[j+1])<<8)|

(((UINT4)input[j+2])<<16)|(((UINT4)input[j+3])<<24);

}

////////////////////////////////////////////////////////////////////////////////

//md5test.cpp:Definestheentrypointfortheconsoleapplication.

//

#include"stdafx.h"

#include"string.h"

intmain(intargc,char*argv[])

{

MD5_CTXmd5;

MD5Init(&md5);//初始化用于md5加密的结构

unsignedcharencrypt[200];//存放于加密的信息

unsignedchardecrypt[17];//存放加密后的结果

scanf("%s",encrypt);//输入加密的字符

MD5Update(&md5,encrypt,strlen((char*)encrypt));//对欲加密的字符进行加密MD5Final(decrypt,&md5);//获得最终结果

printf("加密前:%s/n加密后:",encrypt);

for(inti=0;i<16;i++)

printf("%2x",decrypt[i]);

printf("/n/n/n加密结束!/n");

return0;

}

/*以上代码在vc6下编译通过,运行正常,能够得到正确的md5值*/

MD5加密算法-c源代码

md5加密算法c实现 七分注释收藏 经常到csdn来是查资料,每次都会有所收获。总是看别人的感觉很不好意思,于是决定自己也写一点东西贡献出来。于是就有了这篇md5七分注释。希望对用到的朋友有所帮助。 记得当初自己刚开始学习md5的时候,从网上搜了很多关于算法的原理和文字性的描述的东西,但是看了很久一直没有搞懂,搜c的源代码又很少。直到后来学习rsa算法的时候,从网上下了1991年的欧洲的什么组织写的关于rsa、des、md5算法的c源代码(各部分代码混在一块的,比如rsa用到的随机大素数就是用机器的随机时间的md5哈希值获得的)。我才彻底把md5弄明白了。这里的代码就是我从那里面分离出来的,代码的效率和可重用性都是很高的。整理了一下希望对需要的朋友能够有帮助。 md5的介绍的文章网上很多,关于md5的来历,用途什么的这里就不再介绍了。这里主要介绍代码。代码明白了就什么都明白了。 //////////////////////////////////////////////////////////////////// /* md5.h */ #ifndef _MD5_H_ #define _MD5_H_ #define R_memset(x, y, z) memset(x, y, z) #define R_memcpy(x, y, z) memcpy(x, y, z) #define R_memcmp(x, y, z) memcmp(x, y, z) typedef unsigned long UINT4; typedef unsigned char *POINTER; /* MD5 context. */ typedef struct { /* state (ABCD) */ /*四个32bits数,用于存放最终计算得到的消息摘要。当消息长度〉512bits时,也用于存放每个512bits的中间结果*/ UINT4 state[4]; /* number of bits, modulo 2^64 (lsb first) */ /*存储原始信息的bits数长度,不包括填充的bits,最长为2^64 bits,因为2^64是一个64位数的最大值*/ UINT4 count[2]; /* input buffer */ /*存放输入的信息的缓冲区,512bits*/ unsigned char buffer[64];

MD5算法及源代码

MD5算法及源代码 分类:计算机密码 //获得MD5的二个数组和一个buffer并初始化 MD5 *GetMD5(); //初始化MD5的二个数据和一个buffer void MD5Init (MD5 *context); //用于计算MD5值的函数 void MD5Update (MD5 *context, unsigned char *input, unsigned int inputLen); //输出结果 void MD5Final (MD5 *context, unsigned char digest[16]); //对input数据做一次完整的MD5运算 void MD5Out (MD5 *md5, unsigned char *input, unsigned int inputLen, unsigned char out[16]); //计算一个文件的MD5值 int 计算一个文件的MD5值(TCHAR* 文件路径, unsigned char md5值[16]) { MD5 context; int 缓冲区长度 = 1024, 读取到的字节数; unsigned char *缓冲区 = new unsigned char[缓冲区长度]; FILE *文件指针 = fopen(文件路径, "rb"); if(文件指针 == NULL) return 1; MD5Init(&context); while ( (读取到的字节数 = fread ( 缓冲区, 1, 缓冲区长度, 文件指针 )) ! =EOF) { MD5Update (&context, 缓冲区, 读取到的字节数); //判断是否为已经读到文件尾 if ( 读取到的字节数 < 缓冲区长度 ) break; } MD5Final (&context, md5值); free ( 缓冲区 ); return 0; } /** **MD5.h **/ typedef struct { unsigned long state[4]; /* state (ABCD) */ unsigned long count[2]; /* number of bits, modulo 2^64 */

MD5算法的设计与实现

实验三 MD5算法的设计与实现 一、实验目的: 设计并实现MD5算法,从而进一步加深对数据完整性保证和散列函数的理解。 二、实验要求: 1、产生任意电子文档(包括文本和二进制)的128位信息摘要。 2、根据信息摘要验证该电子文档是否被更改过。 三、实验内容: 1、MD5算法简介: Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。1991年,Rivest开发出技术上更为趋近成熟的md5算法。它在MD4的基础上增加了"安全-带子"(safety-belts)的概念。虽然MD5比MD4复杂度大一些,但却更为安全。这个算法很明显的由四个和MD4设计有少许不同的步骤组成。在MD5算法中,信息-摘要的大小和填充的必要条件与MD4完全相同。Den boer和Bosselaers曾发现MD5算法中的假冲突(pseudo-collisions),但除此之外就没有其他被发现的加密后结果了。对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。

2. MD5算法逻辑处理操作包括以下几步: 步骤一:附加填充比特。对报文填充使报文的长度(比特数)与448模512同余。即填充比特使长度为512的整数倍减去64。例如,如果报文是448比特长,那么将填充512比特形成960比特的报文。填充比特串的最高位为1,其余各位均为0。 步骤二:附加长度值。将用64比特表示的初始报文(填充前)的位长度附加在步骤一的结果后(低位字节优先)。如果初始长度大于264,仅使用该长度的低64比特。这样,该域所包含的长度值为初始报文长度模264的值。这两步的结果将产生一个长度为512整数倍比特的报文。经扩展的报文表示成512比特的分组序列列Y1、Y2、Y3……Y(n-1),因此扩展的报文长度等于L乘512比特。与之等价的是,该结果也等于字长为16比特或32比特的整数倍,如果让[]10?NML表示扩展报文包含的字数,其中N是16的倍数,则N等于L 乘512。下图为使用MD5产生报文摘要的过程:

MD5加密算法原理

MD5加密算法原理 MD5的全称是Message-Digest Algorithm 5(信息-摘要算法),在90年代初由MIT Laboratory for Computer Science和RSA Data Security Inc的Ronald L. Rivest开发出来,经MD2、MD3和MD4发展而来。它的作用是让大容量信息在用数字签名软件签署私人密匙前被"压缩"成一种保密的格式(就是把一个任意长度的字节串变换成一定长的大整数)。不管是MD2、MD4还是MD5,它们都需要获得一个随机长度的信息并产生一个128位的信息摘要。虽然这些算法的结构或多或少有些相似,但MD2的设计与MD4和MD5完全不同,那是因为MD2是为8位机器做过设计优化的,而MD4和MD5却是面向32位的电脑。这三个算法的描述和C语言源代码在Internet RFCs 1321中有详细的描述 (https://www.sodocs.net/doc/986821856.html,/rfc/rfc1321.txt),这是一份最权威的文档,由Ronald L. Rivest 在1992年8月向IEFT提交。. . Van Oorschot和Wiener曾经考虑过一个在散列中暴力搜寻冲突的函数(Brute-Force Hash Function),而且他们猜测一个被设计专门用来搜索MD5冲突的机器(这台机器在1994年的制造成本大约是一百万美元)可以平均每24天就找到一个冲突。但单从1991年到2001年这10年间,竟没有出现替代MD5算法的MD6或被叫做其他什么名字的新算法这一点,我们就可以看出这个瑕疵并没有太多的影响MD5的安全性。上面所有这些都不足以成为MD5 的在实际应用中的问题。并且,由于MD5算法的使用不需要支付任何版权费用的,所以在一般的情况下(非绝密应用领域。但即便是应用在绝密领域内,MD5也不失为一种非常优秀的中间技术),MD5怎么都应该算得上是非常安全的了。 算法的应用 MD5的典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止被篡改。比如,在UNIX下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如: MD5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461 这就是tanajiya.tar.gz文件的数字签名。MD5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的MD5信息摘要。如果在以后传播这个文件的过程中,无论文件的内容发生了任何形式的改变(包括人为修改或者下载过程中线路不稳定引起的传输错误等),只要你对这个文件重新计算MD5时就会发现信息摘要不相同,由此可以确定你得到的只是一个不正确的文件。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的"抵赖",这就是所谓的数字签名应用。 MD5还广泛用于加密和解密技术上。比如在UNIX系统中用户的密码就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。

md5算法的应用

算法的应用 md5的典型应用是对一段信息(message)产生信息摘要(message-digest),以防止被篡改。比如,在unix 下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如: md5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461 这就是tanajiya.tar.gz文件的数字签名。md5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的md5信息摘要。如果在以后传播这个文件的过程中,无论文件的内容发生了任何形式的改变(包括人为修改或者下载过程中线路不稳定引起的传输错误等),只要你对这个文件重新计算md5时就会发现信息摘要不相同,由此可以确定你得到的只是一个不正确的文件。如果再有一个第三方的认证机构,用md5还可以防止文件作者的"抵赖",这就是所谓的数字签名应用。 md5还广泛用于加密和解密技术上。比如在unix系统中用户的密码就是以md5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成md5值,然后再去和保存在文件系统中的md5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。 正是因为这个原因,现在被黑客使用最多的一种破译密码的方法就是一种被称为"跑字典"的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用md5程序计算出这

md5计算程序源代码

//以下为md5计算程序源代码,可以复制到自己的程序中使用,使用方法见最后的main函数 //经测试,绝对可以使用 ////////////////////////////////////////////////////// #include #include #include using namespace std; /* Type define */ typedef unsigned char byte; typedef unsigned int uint32; using std::string; using std::ifstream; /* MD5 declaration. */ class MD5 { public: MD5(); MD5(const void* input, size_t length); MD5(const string& str); MD5(ifstream& in); void update(const void* input, size_t length); void update(const string& str); void update(ifstream& in); const byte* digest(); string toString(); void reset(); private: void update(const byte* input, size_t length); void final(); void transform(const byte block[64]); void encode(const uint32* input, byte* output, size_t length); void decode(const byte* input, uint32* output, size_t length); string bytesToHexString(const byte* input, size_t length); /* class uncopyable */ MD5(const MD5&); MD5& operator=(const MD5&);

MD5算法

/* md5.h */ #ifndef _MD5_H_ #define _MD5_H_ #define R_memset(x, y, z) memset(x, y, z) #define R_memcpy(x, y, z) memcpy(x, y, z) #define R_memcmp(x, y, z) memcmp(x, y, z) typedef unsigned long UINT4; typedef unsigned char *POINTER; /* MD5 context. */ typedef struct { /* state (ABCD) */ /*四个32bits数,用于存放最终计算得到的消息摘要。当消息长度〉64字节时,也用于存放每个64字节的中间结果*/ UINT4 state[4]; /* number of bits, modulo 2^64 (lsb first) */ /*存储原始信息的bits数长度,不包括填充的bits,最长为

2^64 bits,因为2^64是一个64位数的最大值*/ UINT4 count[2]; /* input buffer */ /*存放输入的信息的缓冲区,64字节*/ unsigned char buffer[64]; } MD5_CTX; void MD5Init(MD5_CTX *); void MD5Update(MD5_CTX *, unsigned char *, unsigned int); void MD5Final(unsigned char [16], MD5_CTX *); #endif /* _MD5_H_ */ /////////////////////////////////////////////////////////////////// //////// /* md5.cpp */ #include "stdafx.h" /* Constants for MD5Transform routine. */

MD5加密原理和Java实现

MD5加密原理和Java实现 MD5加密算法为现在应用最广泛的哈希算法之一,该算法广泛应用于互联网网站的用户文件加密,能够将用户密码加密为128位的长整数。数据库并不明文存储用户密码,而是在用户登录时将输入密码字符串进行MD5加密,与数据库中所存储的MD5值匹配,从而降低密码数据库被盗取后用户损失的风险。 Md5加密算法原理 MD5加密算法以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。 在MD5加密算法中,首先需要对信息进行填充,使其字节长度对512求余数的结果等于448。因此,信息的字节长度(Bits Length)将被扩展至N*512+448,即N*64+56个字节(Bytes),N为一个正整数。 填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后再在这个结果后面附加一个以64位二进制表示的填充前的信息长度。经过这两步的处理,现在的信息字节长度=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍数。这样做的原因是为满足后面处理中对信息长度的要求。 MD5中有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x01234567,B=0x89abcdef,C=0xfedcba98,D=0x76543210 当设置好这四个链接变量后,就开始进入算法的四轮循环运算,循环的次数是信息中512位信息分组的数目。 将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量(文本中的一个子分组和一个常数)。再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。以一下是每次操作中用到的四个非线性函数(每轮一个)。 F(X,Y,Z)=(X∧Y)∨(( X)∧Z) G(X,Y,Z)=(X∧Z)∨(Y∧( Z)) H(X,Y,Z)=X?Y?Z I(X,Y,Z)=Y?(X∨( Z)) 其中,?是异或,∧是与,∨是或,!是反符号。 如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。F 是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。所有这些完成之后,将A,B,C,D分别加上a,b,c,d。然后用下一分组数据继续运行算法,最后的输出是A,B,C和D的级联。最后得到的A,B,C,D就是输出结果,A是低位,D为高位,DCBA组成128位输出结果。代码实现: package encryption; /** * md5 类实现了RSA Data Security, Inc.在提交给IETF 的RFC1321中的MD5 message-digest 算法。 **/

MD5原理[百度百科]

原理 对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。 在MD5算法中,首先需要对信息进行填充,使其位长对512求余的结果等于448。因此,信息的位长(Bits Length)将被扩展至N*512+448,N为一个非负整数,N可以是零。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,信息的位长=N*512+448+64= (N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。总体流程如下图所示,表示第i个分组,每次的运算都由前一轮的128位结果值和第i块512bit值进行运算。初始的128位值为初试链接变量,这些参数用于第一轮的运算,以大端字节序来表示,他们分别为:A=0x01234567,B=0x89ABCDEF,C=0xFEDCBA98,D=0x76543210。 MD5算法的整体流程图[1]

每一分组的算法流程如下: a)第一分组需要将上面四个链接变量复制到另外四个变量中:A到a,B到b,C 到c,D到d。从第二分组开始的变量为上一分组的运算结果。 主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。 每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向左环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。 以下是每次操作中用到的四个非线性函数(每轮一个)。 F(X,Y,Z) =(X&Y)|((~X)&Z) G(X,Y,Z) =(X&Z)|(Y&(~Z)) H(X,Y,Z) =X^Y^Z I(X,Y,Z)=Y^(X|(~Z)) (&;是与,|是或,~是非,^是异或) 这四个函数的说明:如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。 F是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。 假设Mj表示消息的第j个子分组(从0到15),常数ti是4294967296*abs(sin(i))的整数部分,i取值从1到64,单位是弧度。(4294967296等于2的32次方)FF(a,b,c,d,Mj,s,ti)表示 a = b + ((a + F(b,c,d) + Mj + ti) << s) GG(a,b,c,d,Mj,s,ti)表示 a = b + ((a + G(b,c,d) + Mj + ti) << s) HH(a,b,c,d,Mj,s,ti)表示 a = b + ((a + H(b,c,d) + Mj + ti) << s) Ⅱ(a,b,c,d,Mj,s,ti)表示 a = b + ((a + I(b,c,d) + Mj + ti) << s) 这四轮(64步)是: 第一轮 FF(a,b,c,d,M0,7,0xd76aa478) FF(d,a,b,c,M1,12,0xe8c7b756) FF(c,d,a,b,M2,17,0x242070db) FF(b,c,d,a,M3,22,0xc1bdceee) FF(a,b,c,d,M4,7,0xf57c0faf) FF(d,a,b,c,M5,12,0x4787c62a) FF(c,d,a,b,M6,17,0xa8304613) FF(b,c,d,a,M7,22,0xfd469501) FF(a,b,c,d,M8,7,0x698098d8) FF(d,a,b,c,M9,12,0x8b44f7af) FF(c,d,a,b,M10,17,0xffff5bb1) FF(b,c,d,a,M11,22,0x895cd7be) FF(a,b,c,d,M12,7,0x6b901122) FF(d,a,b,c,M13,12,0xfd987193) FF(c,d,a,b,M14,17,0xa679438e) FF(b,c,d,a,M15,22,0x49b40821) 第二轮 GG(a,b,c,d,M1,5,0xf61e2562)

MD5算法实验C++

一、实验目的 验证MD5加密算法,了解加密过程。 二、实验环境 软件工具:Visual C++ 6.0 操作系统:windows xp 三、实验思想 对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。 在MD5算法中,首先需要对信息进行填充,使其位长对512求余的结果等于448。因此,信息的位长(Bits Length)将被扩展至N*512+448,N为一个非负整数,N可以是零。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,现在的信息的位长=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。 MD5中有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x67452301,B=0xefcdab89,C=0x98badcfe,D=0x10325476。 当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的次数是信息中512位信息分组的数目。 将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向左环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。 四、实验数据(源代码) #include "global.h" #include "md5.h" /* Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10

MD5加密解密算法的描述

MD5 算法描述 对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。 在MD5算法中,首先需要对信息进行填充,使其字节长度对512求余的结果等于448。因此,信息的字节长度(Bits Length)将被扩展至N*512+448,即N*64+56个字节(Bytes),N为一个正整数。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,现在的信息字节长度=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。 MD5中有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x01234567,B=0x89abcdef,C=0xfedcba98,D=0x76543210。 当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的次数是信息中512位信息分组的数目。

将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。 主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。 以一下是每次操作中用到的四个非线性函数(每轮一个)。 F(X,Y,Z) =(X&Y)|((~X)&Z) G(X,Y,Z) =(X&Z)|(Y&(~Z)) H(X,Y,Z) =X^Y^Z I(X,Y,Z)=Y^(X|(~Z)) (&是与,|是或,~是非,^是异或) 这四个函数的说明:如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。 F是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。

MD5算法实现解读

md5加密算法c实现 md5的介绍的文章网上很多,关于md5的来历,用途什么的这里就不再介绍了。这里主要介绍代码。代码明白了就什么都明白了。 //////////////////////////////////////////////////////////////////// /*md5.h*/ #ifndef_MD5_H_ #define_MD5_H_ #defineR_memset(x,y,z)memset(x,y,z) #defineR_memcpy(x,y,z)memcpy(x,y,z) #defineR_memcmp(x,y,z)memcmp(x,y,z) typedefunsignedlongUINT4; typedefunsignedchar*POINTER; /*MD5context.*/ typedefstruct{ /*state(ABCD)*/ /*四个32bits数,用于存放最终计算得到的消息摘要。当消息长度〉512bits时,也用于存放每个512bits的中间结果*/ UINT4state[4]; /*numberofbits,modulo2^64(lsbfirst)*/ /*存储原始信息的bits数长度,不包括填充的bits,最长为2^64bits,因为2^64是一个64位数的最大值*/ UINT4count[2]; /*inputbuffer*/ /*存放输入的信息的缓冲区,512bits*/ unsignedcharbuffer[64]; }MD5_CTX; voidMD5Init(MD5_CTX*); voidMD5Update(MD5_CTX*,unsignedchar*,unsignedint); voidMD5Final(unsignedchar[16],MD5_CTX*); #endif/*_MD5_H_*/

MD5算法的研究与实现-数据存储加密.

MD5算法的研究与实现-数据存储加密 1 引言随着网络通信技术和Internet的联系日益增强,出现了一系列与网络安全相关的问题:如对主机的攻击,网络上传输的信息被截取、篡改、重发等,由此,它对网络应用的进一步推广构成了巨大威胁,因此密码体制[1]就在这种背景下应运而生了。存储加密涉及大量文件、资料、新建等文档处理,需要高效,可靠的进行各种信息交换,同时对信息流转的整个过程需要有效的组织和监控。对数据的安全存储和安全传输具有较高的要求。数据加密技术不仅具有保证信息机密性的信息加密功能,而且具有数字签名、秘密分存、系统安全等性能。因而可以保障信息的机密性、完整性和准确性,防止信息被篡改、伪造和假冒[2]。虽然目前已有很多加密技术应用于各个领域,但是存在加密强度、运算量大等缺陷,因而本文提出了一种新的加密机制—MD5加密。同时,在竞争日趋激烈的今天,只有实行对数据加密的加强管理,建设性提高信息安全在网络中的地位,以至在竞争中求生存,以期更好地发展下去。 1.1 研究现状 MD5的全称[3]是Message-Digest algorithm 5(信息--摘要算法),MD5是一种不可逆的算法,即对生成的密文求逆,对应着无穷多个逆。在90年代初由MIT Laboratory for Computer Science(IT计算机科学实验室)和RSA Data Security Inc(RSA数据安全公司)的Ronald L.Rivest开发出来,经MD2,MD3和MD4发展而来。它的作用是让大容量信息在用数字签名软件签署私人密钥前被“压缩”成一种保密的格式(把一个任意长度的字节串变换成一定长的大整数)。不管是MD2,MD4还是MD5,它们都需要获得一个随机长度的信息,并产生一个128位的信息摘要。虽然这些算法的结构或多或少有些相似,但是MD2的设计与MD4和MD5完全不同,是因为MD2是为8位机器做过设计优化的,而MD4和MD5却是面向32位的电脑。Rivest在1989年开发出MD2算法,在这个算法中,首先对信息进行数据补位,使信息的字节长度是16的倍数,然后,以一个16位的检验和追加到信息末尾,并且根据这个新产生的信息计算出散列值。后来,Rogier和Chauvaud 发现,如果忽略了检验和,那样就将产生MD2冲突。MD2算法的加密后结果是唯一的---即没有重复。为了加强算法的安全性,Rivest在1990年又开发出MD4算法。MD4算法同样需要填补信息以确保信息的字节长度加上448后能被512整除(信息字节长度mod 512=448。然后,一个以64位二进制表示的信息的最初长度被添加进来。信息被处理成512位迭代结构的区块,而且每个区块要通过三个不同步骤的处理。Den Boer和Bosselaers以及其他人很快的发现了攻击MD4版本中第一步和第三步的漏洞。Dobbertin向大家演示了如何利用一部普通的个人电脑在几分钟内找到MD4完整版本中的冲突(这个冲突实际上是一种漏洞,它将导致对不同的内容进行加密却可能得到相同的加密后结果),毫无疑问,MD4就此被淘汰掉了。一年以后,即1991年,Rivest开发出技术上更为趋近成熟的MD5算法。它在MD4的基础上增加了“安全-带子”(safety-belts)的概念。虽然MD5比MD4稍微慢一些,但却更为安全。这个算法很明显的由四个和MD4设计有少许不同的步骤组成。在MD5算法中,信息--摘要的大小和填充的必要条件与MD4完全相同。Den Boer和Bosselaers曾发现MD5算法中的假冲突(pseudo-collisions),但除此之外就没有其他被发现的加密后结果了。Van Oorschot和Wiener曾经考虑过一个在散列中暴力搜寻冲突的函数(brute-force hash function),而且他们猜测一个被设计专门用来搜索MD5冲

纯代码实现md5算法

纯代码实现md5算法 纯代码实现md5算法 网上已经有C,C++,VB6,java的MD5算法源代码了,甚至已经有了C#的MD5算法代码,唯独https://www.sodocs.net/doc/986821856.html,的MD5算法代码是在是少而又少,因此贴出下列代码供大家雅正。 有人说了,.NET自带MD5算法,何必多此一举呢?如下所示: ‘MD5 Public Shared Function MD5(ByVal strKey As String) As String Dim sPwd As String Dim bytPwd As [Byte]() = ConStrArr(strKey) Dim hashPwd As Byte() = CType(System.Security.Cryptography.CryptoConfig.CreateFro mName("MD5"), _ System.Security.Cryptography.HashAlgorithm).ComputeHash(b ytPwd) sPwd = BitConverter.ToString(hashPwd) sPwd = LCase(sPwd.Replace("-", "")) ‘去掉中间

的"-"符号并转换为小写字母 Return sPwd End Function Public Shared Function MD5(ByVal Key As Byte()) As Byte() Return CType(System.Security.Cryptography.CryptoConfig.CreateFro mName("MD5"), _ System.Security.Cryptography.HashAlgorithm).ComputeHash( Key) End Function 当初写这代码是为了将用了.NET的MD5验证的程序能够用于没有MD5算法的Windows 2000 SP4以下版本,另外也可以更好的了解MD5算法的原理和步骤。 代码如下: Public Class MD5Class MD5 Private Const AA As Integer = &H67452301 Private Const BB As Integer = &HEFCDAB89 Private Const CC As Integer = &H98BADCFE

浅谈使用MD5算法加密数据(完整版)

浅谈使用MD5算法加密用户密码 一、引言 最近看了媒体的一篇关于“网络上公开叫卖个人隐私信息”报导,不法分子通过非法手段获得的个人隐私信息,其详细、准确程度简直令人瞠口结舌。在互联网飞速发展的现在,我们不难想到,网络肯定是传播这些个人隐私信息的重要途径之一。 现在网络上一般的网站,只要稍微完善一点的,都需要用户进行注册,提供诸如用户名、用户密码、电子邮件、甚至是电话号码、详细住址等个人隐私信息,然后才可以享受网站提供的一些特殊的信息或者服务。比如电子商务网站,用户需要购买商品,就一定需要提供详细而准确的信息,而这些信息,往往都是用户的隐私信息,比如电子邮件、电话号码、详细住址等。所以,用户注册的信息对于用户和网站来说都是很重要的资源,不能随意公开,当然也不能存在安全上的隐患。 用户注册时,如果将用户资料直接保存在数据库中,而不施加任何的保密措施,对于一些文件型数据库(如Access),如果有人得到这个数据库文件,那这些资料将全部泄露。再有,如果遇到一个不负责任的网管,则不需要任何技术手段,他就可以查看到用户的任何资料。所以,为了增加安全性,我们有必要对数据库中的隐私数据进行加密,这样,即使有人得到了整个数据库,如果没有解密算法,也一样不能查看到用户的隐私信息。但是,在考虑数据库是否安全之前,有必要对这些数据是否真的那么重要进行考虑,如果数据并不重要,则没有保密的必要,否则将会浪费系统资源、加重程序负担。反之,如果数据具有一定的隐私性,则必须进行加密。因此,在考虑加密以前,应该对数据是否需要加密做出选择,以免浪费系统资源或者留下安全隐患。 二、MD5算法简介 MD5算法,即“Message-Digest Algorithm 5(信息-摘要算法)”,它是由MD2、MD3、MD4发展而来的一种单向函数算法,也就是哈希(HASH)算法,是由国际著名的公钥加密算法标准RSA的第一设计者R.Rivest于上个世纪90年代初开发出来的。 加密算法一般有两种,即单向加密算法和双向加密算法。双向加密是加密算法中最常用的,它将可以直接理解的明文数据加密为不可直接理解的密文数据,在需要的时候,又可以使用一定的算法将这些加密以后的密文数据解密为原来的明文数据。双向加密适合于隐秘通

MD5算法的伪代码

var int[64] r, k //r specifies the per-round shift amounts r[ 0..15]:= {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22} r[16..31]:= {5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20} r[32..47]:= {4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23} r[48..63]:= {6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21} //Use binary integer part of the sines of integers as constants: for i from 0 to 63 k[i] := floor(abs(sin(i + 1)) × 2^32) //Initialize variables: var int h0 := 0x67452301 var int h1 := 0xEFCDAB89 var int h2 := 0x98BADCFE var int h3 := 0x10325476 //Pre-processing: append "1" bit to message append "0" bits until message length in bits ≡ 448 (mod 512) append bit length of message as 64-bit little-endian integer to message //Process the message in successive 512-bit chunks: for each 512-bit chunk of message break chunk into sixteen 32-bit little-endian words w[i], 0 ≤ i ≤ 15 //Initialize hash value for this chunk: var int a := h0 var int b := h1 var int c := h2 var int d := h3 //Main loop: for i from 0 to 63 if 0 ≤ i ≤ 15 then f := (b and c) or ((not b) and d) g := i else if 16 ≤ i ≤ 31 f := (d and b) or ((not d) and c)

MD5加密算法原理

MD5加密算法原理 MD5的Java Bean实现 MD5简介 MD5的全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经MD2、MD3和MD4发展而来。 Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了“字节串”而不是“字符串”这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。 MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。 MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。 MD5还广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的,用户Login的时候,系统是把用户输入的密码计算成MD5值,然后再去和系统中保存的MD5值进行比较,而系统并不“知道”用户的密码是什么。 一些黑客破获这种密码的方法是一种被称为“跑字典”的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。 即使假设密码的最大长度为8,同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是P(62,1)+P(62,2)….+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要TB 级的磁盘组,而且这种方法还有一个前提,就是能获得目标账户的密码MD5值的情况下才可以。 在很多电子商务和社区应用中,管理用户的Account是一种最常用的基本功能,尽管很多Application Server提供了这些基本组件,但很多应用开发者为了管理的更大的灵活性还是喜欢采用关系数据库来管理用户,懒惰的做法是用户的密码往往使用明文或简单的变换后直接保存在数据库中,因此这些用户的密码对软件开发者或系统管理员来说可以说毫无保密可言,本文的目的是介绍MD5的Java Bean的实现,同时给出用MD5来处理用户的Account密码的例子,这种方法使得管理员和程序设计者都无法看到用户的密码,尽管他们可以初始化它们。但重要的一点是对于用户密码设置习惯的保护。 有兴趣的读者可以从这里取得MD5也就是RFC 1321的文本。https://www.sodocs.net/doc/986821856.html,/rfc/rfc1321.txt 实现策略 MD5的算法在RFC1321中实际上已经提供了C的实现,我们其实马上就能想到,至少有两种用Java 实现它的方法,第一种是,用Java语言重新写整个算法,或者再说简单点就是把C程序改写成Java程序。第二种是,用JNI(Java Native Interface)来实现,核心算法仍然用这个C程序,用Java类给它包个壳。

相关主题