- 浏览: 1364323 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
yaolixing01:
他山界面开发框架 v22是一套基于Gecko v22 的开源收 ...
Mozilla FireFox Gecko内核源代码解析(3.nsScanner) -
夏雪纷纷:
感谢博主的分享,好东西啊,哈哈哈,收走了一些,谢谢啊哦,对了, ...
DevExpress DXperience Universal 11.1.6 下载+源码+编译+汉化流程+升级+替换强名 -
夏雪纷纷:
最近有个对于DXperience 2013新功能发布、重难点技 ...
TextEdit非空验证设置 DXperience学习笔记 -
bosschen:
我自己把问价加密,密码为为123456,是rar文件。然后用各 ...
30秒破解所有密码 -
sword319:
现在才发现为什么自己这么苦逼了...哗哗的全是泪啊.. ...
为什么我们程序员晋升要这么难!
MD5算法
MD5(单向散列算法)的全称是Message-Digest Algorithm 5(信息-摘要算法),经MD2、MD3和MD4发展而来。MD5算法的使用不需要支付任何版权费用。
MD5功能:
输入任意长度的信息,经过处理,输出为128位的信息(数字指纹);
不同的输入得到的不同的结果(唯一性);
根据128位的输出结果不可能反推出输入的信息(不可逆);
MD5属不属于加密算法:
认为不属于的人是因为他们觉得不能从密文(散列值)反过来得到原文,即没有解密算法,所以这部分人认为MD5只能属于算法,不能称为加密算法;
认为属于的人是因为他们觉得经过MD5处理后看不到原文,即已经将原文加密,所以认为MD5属于加密算法;我个人支持后者。
MD5用途:
1、防止被篡改:
1)比如发送一个电子文档,发送前,我先得到MD5的输出结果a。然后在对方收到电子文档后,对方也得到一个MD5的输出结果b。如果a与b一样就代表中途未被篡改。2)比如我提供文件下载,为了防止不法分子在安装程序中添加木马,我可以在网站上公布由安装文件得到的MD5输出结果。3)SVN在检测文件是否在CheckOut后被修改过,也是用到了MD5.
2、防止直接看到明文:
现在很多网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。这样就算不法分子得到数据库的用户密码的MD5值,也无法知道用户的密码(其实这样是不安全的,后面我会提到)。(比如在UNIX系统中用户的密码就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。)
3、防止抵赖(数字签名):
这需要一个第三方认证机构。例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。若以后A说这文件不是他写的,权威机构只需对此文件重新产生摘要信息,然后跟记录在册的摘要信息进行比对,相同的话,就证明是A写的了。这就是所谓的“数字签名”。
MD5算法过程:
对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
第一步、填充:如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);
第二步、记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。
第三步、装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有点晕哈,其实想一想就明白了。
第四步、四轮循环运算:循环的次数是分组的个数(N+1)
1)将每一512字节细分成16个小组,每个小组64位(8个字节)
2)先认识四个线性函数(&是与,|是或,~是非,^是异或)
3)设Mj表示消息的第j个子分组(从0到15),<<<s表示循环左移s位,则四种操作为:
4)四轮运算
5)每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环。
如果上面的过程用JAVA代码来实现的话,代码如下:
packagewoxingwosu;



/***//************************************************
*MD5算法
*@author我行我素
*@Date2007-07-01
*************************************************/

publicclassMD5...{


staticfinalStringhexs[]=...{"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
//标准的幻数
privatestaticfinallongA=0x67452301L;
privatestaticfinallongB=0xefcdab89L;
privatestaticfinallongC=0x98badcfeL;
privatestaticfinallongD=0x10325476L;


//下面这些S11-S44实际上是一个4*4的矩阵,在四轮循环运算中用到
staticfinalintS11=7;
staticfinalintS12=12;
staticfinalintS13=17;
staticfinalintS14=22;

staticfinalintS21=5;
staticfinalintS22=9;
staticfinalintS23=14;
staticfinalintS24=20;

staticfinalintS31=4;
staticfinalintS32=11;
staticfinalintS33=16;
staticfinalintS34=23;

staticfinalintS41=6;
staticfinalintS42=10;
staticfinalintS43=15;
staticfinalintS44=21;

//java不支持无符号的基本数据(unsigned)

privatelong[]result=...{A,B,C,D};//存储hash结果,共4×32=128位,初始化值为(幻数的级联)


publicstaticvoidmain(String[]args)...{
MD5md=newMD5();
System.out.println("md5(abc)="+md.digest("abc"));
}


privateStringdigest(StringinputStr)...{
byte[]inputBytes=inputStr.getBytes();
intbyteLen=inputBytes.length;//长度(字节)
intgroupCount=0;//完整分组的个数
groupCount=byteLen/64;//每组512位(64字节)
long[]groups=null;//每个小组(64字节)再细分后的16个小组(4字节)

//处理每一个完整分组

for(intstep=0;step<groupCount;step++)...{
groups=divGroup(inputBytes,step*64);
trans(groups);//处理分组,核心算法
}

//处理完整分组后的尾巴
intrest=byteLen%64;//512位分组后的余数
byte[]tempBytes=newbyte[64];

if(rest<=56)...{
for(inti=0;i<rest;i++)
tempBytes[i]=inputBytes[byteLen-rest+i];

if(rest<56)...{
tempBytes[rest]=(byte)(1<<7);
for(inti=1;i<56-rest;i++)
tempBytes[rest+i]=0;
}
longlen=(long)(byteLen<<3);

for(inti=0;i<8;i++)...{
tempBytes[56+i]=(byte)(len&0xFFL);
len=len>>8;
}
groups=divGroup(tempBytes,0);
trans(groups);//处理分组

}else...{
for(inti=0;i<rest;i++)
tempBytes[i]=inputBytes[byteLen-rest+i];
tempBytes[rest]=(byte)(1<<7);
for(inti=rest+1;i<64;i++)
tempBytes[i]=0;
groups=divGroup(tempBytes,0);
trans(groups);//处理分组

for(inti=0;i<56;i++)
tempBytes[i]=0;
longlen=(long)(byteLen<<3);

for(inti=0;i<8;i++)...{
tempBytes[56+i]=(byte)(len&0xFFL);
len=len>>8;
}
groups=divGroup(tempBytes,0);
trans(groups);//处理分组
}

//将Hash值转换成十六进制的字符串
StringresStr="";
longtemp=0;

for(inti=0;i<4;i++)...{

for(intj=0;j<4;j++)...{
temp=result[i]&0x0FL;
Stringa=hexs[(int)(temp)];
result[i]=result[i]>>4;
temp=result[i]&0x0FL;
resStr+=hexs[(int)(temp)]+a;
result[i]=result[i]>>4;
}
}
returnresStr;
}


/***//**
*从inputBytes的index开始取512位,作为新的分组
*将每一个512位的分组再细分成16个小组,每个小组64位(8个字节)
*@paraminputBytes
*@paramindex
*@return
*/

privatestaticlong[]divGroup(byte[]inputBytes,intindex)...{
long[]temp=newlong[16];

for(inti=0;i<16;i++)...{
temp[i]=b2iu(inputBytes[4*i+index])|
(b2iu(inputBytes[4*i+1+index]))<<8|
(b2iu(inputBytes[4*i+2+index]))<<16|
(b2iu(inputBytes[4*i+3+index]))<<24;
}
returntemp;
}


/***//**
*这时不存在符号位(符号位存储不再是代表正负),所以需要处理一下
*@paramb
*@return
*/

publicstaticlongb2iu(byteb)...{
returnb<0?b&0x7F+128:b;
}


/***//**
*主要的操作,四轮循环
*@paramgroups[]--每一个分组512位(64字节)
*/

privatevoidtrans(long[]groups)...{
longa=result[0],b=result[1],c=result[2],d=result[3];

/**//*第一轮*/

a=FF(a,b,c,d,groups[0],S11,0xd76aa478L);/**//*1*/

d=FF(d,a,b,c,groups[1],S12,0xe8c7b756L);/**//*2*/

c=FF(c,d,a,b,groups[2],S13,0x242070dbL);/**//*3*/

b=FF(b,c,d,a,groups[3],S14,0xc1bdceeeL);/**//*4*/

a=FF(a,b,c,d,groups[4],S11,0xf57c0fafL);/**//*5*/

d=FF(d,a,b,c,groups[5],S12,0x4787c62aL);/**//*6*/

c=FF(c,d,a,b,groups[6],S13,0xa8304613L);/**//*7*/

b=FF(b,c,d,a,groups[7],S14,0xfd469501L);/**//*8*/

a=FF(a,b,c,d,groups[8],S11,0x698098d8L);/**//*9*/

d=FF(d,a,b,c,groups[9],S12,0x8b44f7afL);/**//*10*/

c=FF(c,d,a,b,groups[10],S13,0xffff5bb1L);/**//*11*/

b=FF(b,c,d,a,groups[11],S14,0x895cd7beL);/**//*12*/

a=FF(a,b,c,d,groups[12],S11,0x6b901122L);/**//*13*/

d=FF(d,a,b,c,groups[13],S12,0xfd987193L);/**//*14*/

c=FF(c,d,a,b,groups[14],S13,0xa679438eL);/**//*15*/

b=FF(b,c,d,a,groups[15],S14,0x49b40821L);/**//*16*/


/**//*第二轮*/

a=GG(a,b,c,d,groups[1],S21,0xf61e2562L);/**//*17*/

d=GG(d,a,b,c,groups[6],S22,0xc040b340L);/**//*18*/

c=GG(c,d,a,b,groups[11],S23,0x265e5a51L);/**//*19*/

b=GG(b,c,d,a,groups[0],S24,0xe9b6c7aaL);/**//*20*/

a=GG(a,b,c,d,groups[5],S21,0xd62f105dL);/**//*21*/

d=GG(d,a,b,c,groups[10],S22,0x2441453L);/**//*22*/

c=GG(c,d,a,b,groups[15],S23,0xd8a1e681L);/**//*23*/

b=GG(b,c,d,a,groups[4],S24,0xe7d3fbc8L);/**//*24*/

a=GG(a,b,c,d,groups[9],S21,0x21e1cde6L);/**//*25*/

d=GG(d,a,b,c,groups[14],S22,0xc33707d6L);/**//*26*/

c=GG(c,d,a,b,groups[3],S23,0xf4d50d87L);/**//*27*/

b=GG(b,c,d,a,groups[8],S24,0x455a14edL);/**//*28*/

a=GG(a,b,c,d,groups[13],S21,0xa9e3e905L);/**//*29*/

d=GG(d,a,b,c,groups[2],S22,0xfcefa3f8L);/**//*30*/

c=GG(c,d,a,b,groups[7],S23,0x676f02d9L);/**//*31*/

b=GG(b,c,d,a,groups[12],S24,0x8d2a4c8aL);/**//*32*/


/**//*第三轮*/

a=HH(a,b,c,d,groups[5],S31,0xfffa3942L);/**//*33*/

d=HH(d,a,b,c,groups[8],S32,0x8771f681L);/**//*34*/

c=HH(c,d,a,b,groups[11],S33,0x6d9d6122L);/**//*35*/

b=HH(b,c,d,a,groups[14],S34,0xfde5380cL);/**//*36*/

a=HH(a,b,c,d,groups[1],S31,0xa4beea44L);/**//*37*/

d=HH(d,a,b,c,groups[4],S32,0x4bdecfa9L);/**//*38*/

c=HH(c,d,a,b,groups[7],S33,0xf6bb4b60L);/**//*39*/

b=HH(b,c,d,a,groups[10],S34,0xbebfbc70L);/**//*40*/

a=HH(a,b,c,d,groups[13],S31,0x289b7ec6L);/**//*41*/

d=HH(d,a,b,c,groups[0],S32,0xeaa127faL);/**//*42*/

c=HH(c,d,a,b,groups[3],S33,0xd4ef3085L);/**//*43*/

b=HH(b,c,d,a,groups[6],S34,0x4881d05L);/**//*44*/

a=HH(a,b,c,d,groups[9],S31,0xd9d4d039L);/**//*45*/

d=HH(d,a,b,c,groups[12],S32,0xe6db99e5L);/**//*46*/

c=HH(c,d,a,b,groups[15],S33,0x1fa27cf8L);/**//*47*/

b=HH(b,c,d,a,groups[2],S34,0xc4ac5665L);/**//*48*/


/**//*第四轮*/

a=II(a,b,c,d,groups[0],S41,0xf4292244L);/**//*49*/

d=II(d,a,b,c,groups[7],S42,0x432aff97L);/**//*50*/

c=II(c,d,a,b,groups[14],S43,0xab9423a7L);/**//*51*/

b=II(b,c,d,a,groups[5],S44,0xfc93a039L);/**//*52*/

a=II(a,b,c,d,groups[12],S41,0x655b59c3L);/**//*53*/

d=II(d,a,b,c,groups[3],S42,0x8f0ccc92L);/**//*54*/

c=II(c,d,a,b,groups[10],S43,0xffeff47dL);/**//*55*/

b=II(b,c,d,a,groups[1],S44,0x85845dd1L);/**//*56*/

a=II(a,b,c,d,groups[8],S41,0x6fa87e4fL);/**//*57*/

d=II(d,a,b,c,groups[15],S42,0xfe2ce6e0L);/**//*58*/

c=II(c,d,a,b,groups[6],S43,0xa3014314L);/**//*59*/

b=II(b,c,d,a,groups[13],S44,0x4e0811a1L);/**//*60*/

a=II(a,b,c,d,groups[4],S41,0xf7537e82L);/**//*61*/

d=II(d,a,b,c,groups[11],S42,0xbd3af235L);/**//*62*/

c=II(c,d,a,b,groups[2],S43,0x2ad7d2bbL);/**//*63*/

b=II(b,c,d,a,groups[9],S44,0xeb86d391L);/**//*64*/


/**//*加入到之前计算的结果当中*/
result[0]+=a;
result[1]+=b;
result[2]+=c;
result[3]+=d;
result[0]=result[0]&0xFFFFFFFFL;
result[1]=result[1]&0xFFFFFFFFL;
result[2]=result[2]&0xFFFFFFFFL;
result[3]=result[3]&0xFFFFFFFFL;
}


/***//**
*下面是处理要用到的线性函数
*/

privatestaticlongF(longx,longy,longz)...{
return(x&y)|((~x)&z);
}


privatestaticlongG(longx,longy,longz)...{
return(x&z)|(y&(~z));
}


privatestaticlongH(longx,longy,longz)...{
returnx^y^z;
}


privatestaticlongI(longx,longy,longz)...{
returny^(x|(~z));
}

privatestaticlongFF(longa,longb,longc,longd,longx,longs,

longac)...{
a+=(F(b,c,d)&0xFFFFFFFFL)+x+ac;
a=((a&0xFFFFFFFFL)<<s)|((a&0xFFFFFFFFL)>>>(32-s));
a+=b;
return(a&0xFFFFFFFFL);
}

privatestaticlongGG(longa,longb,longc,longd,longx,longs,

longac)...{
a+=(G(b,c,d)&0xFFFFFFFFL)+x+ac;
a=((a&0xFFFFFFFFL)<<s)|((a&0xFFFFFFFFL)>>>(32-s));
a+=b;
return(a&0xFFFFFFFFL);
}

privatestaticlongHH(longa,longb,longc,longd,longx,longs,

longac)...{
a+=(H(b,c,d)&0xFFFFFFFFL)+x+ac;
a=((a&0xFFFFFFFFL)<<s)|((a&0xFFFFFFFFL)>>>(32-s));
a+=b;
return(a&0xFFFFFFFFL);
}

privatestaticlongII(longa,longb,longc,longd,longx,longs,

longac)...{
a+=(I(b,c,d)&0xFFFFFFFFL)+x+ac;
a=((a&0xFFFFFFFFL)<<s)|((a&0xFFFFFFFFL)>>>(32-s));
a+=b;
return(a&0xFFFFFFFFL);
}
}
MD5安全性:
普遍认为MD5是很安全,因为暴力破解的时间是一般人无法接受的。实际上如果把用户的密码MD5处理后再存储到数据库,其实是很不安全的。因为用户的密码是比较短的,而且很多用户的密码都使用生日,手机号码,身份证号码,电话号码等等。或者使用常用的一些吉利的数字,或者某个英文单词。如果我把常用的密码先MD5处理,把数据存储起来,然后再跟你的MD5结果匹配,这时我就有可能得到明文。比如某个MD5破解网站http://www.cmd5.com/default.aspx,我把其网站下的公告复制如下
我觉得只需要将上面我写的MD5的标准幻数A,B,C,D的值修改一下,修改后也不是MD5算法了,因为不能保证唯一性。这样就算别人得到32位的值,他如果不知道幻数的值是无法还原明文的。就算得到了幻数,也是很难破解的。
JAVA实现MD5
在java中实现MD5是很简单的,在包java.security有个类MessageDigest。官方文档如下
packagewoxingwosu;

/**//************************************************
*MD5算法
*@author我行我素
*@Date2007-07-06
*************************************************/
importjava.security.MessageDigest;


publicclassMyMD5...{


staticchar[]hex=...{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

publicstaticvoidmain(String[]args)...{

try...{
MessageDigestmd5=MessageDigest.getInstance("MD5");//申明使用MD5算法
md5.update("a".getBytes());//
System.out.println("md5(a)="+byte2str(md5.digest()));
md5.update("a".getBytes());
md5.update("bc".getBytes());
System.out.println("md5(abc)="+byte2str(md5.digest()));

}catch(Exceptione)...{
e.printStackTrace();
}
}


/**//**
*将字节数组转换成十六进制字符串
*@parambytes
*@return
*/

privatestaticStringbyte2str(byte[]bytes)...{
intlen=bytes.length;
StringBufferresult=newStringBuffer();

for(inti=0;i<len;i++)...{
bytebyte0=bytes[i];
result.append(hex[byte0>>>4&0xf]);
result.append(hex[byte0&0xf]);
}
returnresult.toString();
}
}
另外附上其他版本的MD5算法的实现(来自网络)
1)JS版的MD5(调用方法:md5(明文))

/**//*
*AJavaScriptimplementationoftheRSADataSecurity,Inc.MD5Message
*DigestAlgorithm,asdefinedinRFC1321.
*Version2.1Copyright(C)PaulJohnston1999-2002.
*Othercontributors:GregHolt,AndrewKepert,Ydnar,Lostinet
*DistributedundertheBSDLicense
*Seehttp://pajhome.org.uk/crypt/md5formoreinfo.
*/


/**//*
*Configurablevariables.Youmayneedtotweakthesetobecompatiblewith
*theserver-side,butthedefaultsworkinmostcases.
*/

varhexcase=1;/**//*hexoutputformat.0-lowercase;1-uppercase*/

varb64pad="";/**//*base-64padcharacter."="forstrictRFCcompliance*/

varchrsz=8;/**//*bitsperinputcharacter.8-ASCII;16-Unicode*/


/**//*
*Thesearethefunctionsyou'llusuallywanttocall
*Theytakestringargumentsandreturneitherhexorbase-64encodedstrings
*/

functionhex_md5(s)...{returnbinl2hex(core_md5(str2binl(s),s.length*chrsz));}

functionstr_md5(s)...{returnbinl2str(core_md5(str2binl(s),s.length*chrsz));}

functionhex_hmac_md5(key,data)...{returnbinl2hex(core_hmac_md5(key,data));}

functionstr_hmac_md5(key,data)...{returnbinl2str(core_hmac_md5(key,data));}


/**//*
*CalculatetheMD5ofanarrayoflittle-endianwords,andabitlength
*/
functioncore_md5(x,len)

...{

/**//*appendpadding*/
x[len>>5]|=0x80<<((len)%32);
x[(((len+64)>>>9)<<4)+14]=len;

vara=1732584193;
varb=-271733879;
varc=-1732584194;
vard=271733878;

for(vari=0;i<x.length;i+=16)

...{
varolda=a;
varoldb=b;
varoldc=c;
varoldd=d;

a=md5_ff(a,b,c,d,x[i+0],7,-680876936);
d=md5_ff(d,a,b,c,x[i+1],12,-389564586);
c=md5_ff(c,d,a,b,x[i+2],17,606105819);
b=md5_ff(b,c,d,a,x[i+3],22,-1044525330);
a=md5_ff(a,b,c,d,x[i+4],7,-176418897);
d=md5_ff(d,a,b,c,x[i+5],12,1200080426);
c=md5_ff(c,d,a,b,x[i+6],17,-1473231341);
b=md5_ff(b,c,d,a,x[i+7],22,-45705983);
a=md5_ff(a,b,c,d,x[i+8],7,1770035416);
d=md5_ff(d,a,b,c,x[i+9],12,-1958414417);
c=md5_ff(c,d,a,b,x[i+10],17,-42063);
b=md5_ff(b,c,d,a,x[i+11],22,-1990404162);
a=md5_ff(a,b,c,d,x[i+12],7,1804603682);
d=md5_ff(d,a,b,c,x[i+13],12,-40341101);
c=md5_ff(c,d,a,b,x[i+14],17,-1502002290);
b=md5_ff(b,c,d,a,x[i+15],22,1236535329);

a=md5_gg(a,b,c,d,x[i+1],5,-165796510);
d=md5_gg(d,a,b,c,x[i+6],9,-1069501632);
c=md5_gg(c,d,a,b,x[i+11],14,643717713);
b=md5_gg(b,c,d,a,x[i+0],20,-373897302);
a=md5_gg(a,b,c,d,x[i+5],5,-701558691);
d=md5_gg(d,a,b,c,x[i+10],9,38016083);
c=md5_gg(c,d,a,b,x[i+15],14,-660478335);
b=md5_gg(b,c,d,a,x[i+4],20,-405537848);
a=md5_gg(a,b,c,d,x[i+9],5,568446438);
d=md5_gg(d,a,b,c,x[i+14],9,-1019803690);
c=md5_gg(c,d,a,b,x[i+3],14,-187363961);
b=md5_gg(b,c,d,a,x[i+8],20,1163531501);
a=md5_gg(a,b,c,d,x[i+13],5,-1444681467);
d=md5_gg(d,a,b,c,x[i+2],9,-51403784);
c=md5_gg(c,d,a,b,x[i+7],14,1735328473);
b=md5_gg(b,c,d,a,x[i+12],20,-1926607734);

a=md5_hh(a,b,c,d,x[i+5],4,-378558);
d=md5_hh(d,a,b,c,x[i+8],11,-2022574463);
c=md5_hh(c,d,a,b,x[i+11],16,1839030562);
b=md5_hh(b,c,d,a,x[i+14],23,-35309556);
a=md5_hh(a,b,c,d,x[i+1],4,-1530992060);
d=md5_hh(d,a,b,c,x[i+4],11,1272893353);
c=md5_hh(c,d,a,b,x[i+7],16,-155497632);
b=md5_hh(b,c,d,a,x[i+10],23,-1094730640);
a=md5_hh(a,b,c,d,x[i+13],4,681279174);
d=md5_hh(d,a,b,c,x[i+0],11,-358537222);
c=md5_hh(c,d,a,b,x[i+3],16,-722521979);
b=md5_hh(b,c,d,a,x[i+6],23,76029189);
a=md5_hh(a,b,c,d,x[i+9],4,-640364487);
d=md5_hh(d,a,b,c,x[i+12],11,-421815835);
c=md5_hh(c,d,a,b,x[i+15],16,530742520);
b=md5_hh(b,c,d,a,x[i+2],23,-995338651);

a=md5_ii(a,b,c,d,x[i+0],6,-198630844);
d=md5_ii(d,a,b,c,x[i+7],10,1126891415);
c=md5_ii(c,d,a,b,x[i+14],15,-1416354905);
b=md5_ii(b,c,d,a,x[i+5],21,-57434055);
a=md5_ii(a,b,c,d,x[i+12],6,1700485571);
d=md5_ii(d,a,b,c,x[i+3],10,-1894986606);
c=md5_ii(c,d,a,b,x[i+10],15,-1051523);
b=md5_ii(b,c,d,a,x[i+1],21,-2054922799);
a=md5_ii(a,b,c,d,x[i+8],6,1873313359);
d=md5_ii(d,a,b,c,x[i+15],10,-30611744);
c=md5_ii(c,d,a,b,x[i+6],15,-1560198380);
b=md5_ii(b,c,d,a,x[i+13],21,1309151649);
a=md5_ii(a,b,c,d,x[i+4],6,-145523070);
d=md5_ii(d,a,b,c,x[i+11],10,-1120210379);
c=md5_ii(c,d,a,b,x[i+2],15,718787259);
b=md5_ii(b,c,d,a,x[i+9],21,-343485551);

a=safe_add(a,olda);
b=safe_add(b,oldb);
c=safe_add(c,oldc);
d=safe_add(d,oldd);
}
returnArray(a,b,c,d);

}


/**//*
*Thesefunctionsimplementthefourbasicoperationsthealgorithmuses.
*/
functionmd5_cmn(q,a,b,x,s,t)

...{
returnsafe_add(bit_rol(safe_add(safe_add(a,q),safe_add(x,t)),s),b);
}
functionmd5_ff(a,b,c,d,x,s,t)

...{
returnmd5_cmn((b&c)|((~b)&d),a,b,x,s,t);
}
functionmd5_gg(a,b,c,d,x,s,t)

...{
returnmd5_cmn((b&d)|(c&(~d)),a,b,x,s,t);
}
functionmd5_hh(a,b,c,d,x,s,t)

...{
returnmd5_cmn(b^c^d,a,b,x,s,t);
}
functionmd5_ii(a,b,c,d,x,s,t)

...{
returnmd5_cmn(c^(b|(~d)),a,b,x,s,t);
}


/**//*
*CalculatetheHMAC-MD5,ofakeyandsomedata
*/
functioncore_hmac_md5(key,data)

...{
varbkey=str2binl(key);
if(bkey.length>16)bkey=core_md5(bkey,key.length*chrsz);

varipad=Array(16),opad=Array(16);
for(vari=0;i<16;i++)

...{
ipad[i]=bkey[i]^0x36363636;
opad[i]=bkey[i]^0x5C5C5C5C;
}

varhash=core_md5(ipad.concat(str2binl(data)),512+data.length*chrsz);
returncore_md5(opad.concat(hash),512+128);
}


/**//*
*Addintegers,wrappingat2^32.Thisuses16-bitoperationsinternally
*toworkaroundbugsinsomeJSinterpreters.
*/
functionsafe_add(x,y)

...{
varlsw=(x&0xFFFF)+(y&0xFFFF);
varmsw=(x>>16)+(y>>16)+(lsw>>16);
return(msw<<16)|(lsw&0xFFFF);
}


/**//*
*Bitwiserotatea32-bitnumbertotheleft.
*/
functionbit_rol(num,cnt)

...{
return(num<<cnt)|(num>>>(32-cnt));
}


/**//*
*Convertastringtoanarrayoflittle-endianwords
*IfchrszisASCII,characters>255havetheirhi-bytesilentlyignored.
*/
functionstr2binl(str)

...{
varbin=Array();
varmask=(1<<chrsz)-1;
for(vari=0;i<str.length*chrsz;i+=chrsz)
bin[i>>5]|=(str.charCodeAt(i/chrsz)&mask)<<(i%32);
returnbin;
}


/**//*
*Convertanarrayoflittle-endianwordstoastring
*/
functionbinl2str(bin)

...{
varstr="";
varmask=(1<<chrsz)-1;
for(vari=0;i<bin.length*32;i+=chrsz)
str+=String.fromCharCode((bin[i>>5]>>>(i%32))&mask);
returnstr;
}


/**//*
*Convertanarrayoflittle-endianwordstoahexstring.
*/
functionbinl2hex(binarray)

...{
varhex_tab=hexcase?"0123456789ABCDEF":"0123456789abcdef";
varstr="";
for(vari=0;i<binarray.length*4;i++)

...{
str+=hex_tab.charAt((binarray[i>>2]>>((i%4)*8+4))&0xF)+
hex_tab.charAt((binarray[i>>2]>>((i%4)*8))&0xF);
}
returnstr;
}


String.prototype.trim=function()...{returnthis.replace(/(^s*)|(s*$)/g,"");}


functionmd5(text)...{
returnhex_md5(text.trim());
}
MD5功能:
输入任意长度的信息,经过处理,输出为128位的信息(数字指纹);
不同的输入得到的不同的结果(唯一性);
根据128位的输出结果不可能反推出输入的信息(不可逆);
MD5属不属于加密算法:
认为不属于的人是因为他们觉得不能从密文(散列值)反过来得到原文,即没有解密算法,所以这部分人认为MD5只能属于算法,不能称为加密算法;
认为属于的人是因为他们觉得经过MD5处理后看不到原文,即已经将原文加密,所以认为MD5属于加密算法;我个人支持后者。
MD5用途:
1、防止被篡改:
1)比如发送一个电子文档,发送前,我先得到MD5的输出结果a。然后在对方收到电子文档后,对方也得到一个MD5的输出结果b。如果a与b一样就代表中途未被篡改。2)比如我提供文件下载,为了防止不法分子在安装程序中添加木马,我可以在网站上公布由安装文件得到的MD5输出结果。3)SVN在检测文件是否在CheckOut后被修改过,也是用到了MD5.
2、防止直接看到明文:
现在很多网站在数据库存储用户的密码的时候都是存储用户密码的MD5值。这样就算不法分子得到数据库的用户密码的MD5值,也无法知道用户的密码(其实这样是不安全的,后面我会提到)。(比如在UNIX系统中用户的密码就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。)
3、防止抵赖(数字签名):
这需要一个第三方认证机构。例如A写了一个文件,认证机构对此文件用MD5算法产生摘要信息并做好记录。若以后A说这文件不是他写的,权威机构只需对此文件重新产生摘要信息,然后跟记录在册的摘要信息进行比对,相同的话,就证明是A写的了。这就是所谓的“数字签名”。
MD5算法过程:
对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
第一步、填充:如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit);
第二步、记录信息长度:用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位。
第三步、装入标准的幻数(四个整数):标准的幻数(物理顺序)是(A=(01234567)16,B=(89ABCDEF)16,C=(FEDCBA98)16,D=(76543210)16)。如果在程序中定义应该是(A=0X67452301L,B=0XEFCDAB89L,C=0X98BADCFEL,D=0X10325476L)。有点晕哈,其实想一想就明白了。
第四步、四轮循环运算:循环的次数是分组的个数(N+1)
1)将每一512字节细分成16个小组,每个小组64位(8个字节)
2)先认识四个线性函数(&是与,|是或,~是非,^是异或)
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))
G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=X^Y^Z
I(X,Y,Z)=Y^(X|(~Z))
3)设Mj表示消息的第j个子分组(从0到15),<<<s表示循环左移s位,则四种操作为:
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)
II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(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)
II(a,b,c,d,Mj,s,ti)表示a=b+((a+I(b,c,d)+Mj+ti)<<<s)
4)四轮运算
第一轮
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)
第二轮
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三轮
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)
第四轮
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
a=FF(a,b,c,d,M0,7,0xd76aa478)
b=FF(d,a,b,c,M1,12,0xe8c7b756)
c=FF(c,d,a,b,M2,17,0x242070db)
d=FF(b,c,d,a,M3,22,0xc1bdceee)
a=FF(a,b,c,d,M4,7,0xf57c0faf)
b=FF(d,a,b,c,M5,12,0x4787c62a)
c=FF(c,d,a,b,M6,17,0xa8304613)
d=FF(b,c,d,a,M7,22,0xfd469501)
a=FF(a,b,c,d,M8,7,0x698098d8)
b=FF(d,a,b,c,M9,12,0x8b44f7af)
c=FF(c,d,a,b,M10,17,0xffff5bb1)
d=FF(b,c,d,a,M11,22,0x895cd7be)
a=FF(a,b,c,d,M12,7,0x6b901122)
b=FF(d,a,b,c,M13,12,0xfd987193)
c=FF(c,d,a,b,M14,17,0xa679438e)
d=FF(b,c,d,a,M15,22,0x49b40821)
第二轮
a=GG(a,b,c,d,M1,5,0xf61e2562)
b=GG(d,a,b,c,M6,9,0xc040b340)
c=GG(c,d,a,b,M11,14,0x265e5a51)
d=GG(b,c,d,a,M0,20,0xe9b6c7aa)
a=GG(a,b,c,d,M5,5,0xd62f105d)
b=GG(d,a,b,c,M10,9,0x02441453)
c=GG(c,d,a,b,M15,14,0xd8a1e681)
d=GG(b,c,d,a,M4,20,0xe7d3fbc8)
a=GG(a,b,c,d,M9,5,0x21e1cde6)
b=GG(d,a,b,c,M14,9,0xc33707d6)
c=GG(c,d,a,b,M3,14,0xf4d50d87)
d=GG(b,c,d,a,M8,20,0x455a14ed)
a=GG(a,b,c,d,M13,5,0xa9e3e905)
b=GG(d,a,b,c,M2,9,0xfcefa3f8)
c=GG(c,d,a,b,M7,14,0x676f02d9)
d=GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三轮
a=HH(a,b,c,d,M5,4,0xfffa3942)
b=HH(d,a,b,c,M8,11,0x8771f681)
c=HH(c,d,a,b,M11,16,0x6d9d6122)
d=HH(b,c,d,a,M14,23,0xfde5380c)
a=HH(a,b,c,d,M1,4,0xa4beea44)
b=HH(d,a,b,c,M4,11,0x4bdecfa9)
c=HH(c,d,a,b,M7,16,0xf6bb4b60)
d=HH(b,c,d,a,M10,23,0xbebfbc70)
a=HH(a,b,c,d,M13,4,0x289b7ec6)
b=HH(d,a,b,c,M0,11,0xeaa127fa)
c=HH(c,d,a,b,M3,16,0xd4ef3085)
d=HH(b,c,d,a,M6,23,0x04881d05)
a=HH(a,b,c,d,M9,4,0xd9d4d039)
b=HH(d,a,b,c,M12,11,0xe6db99e5)
c=HH(c,d,a,b,M15,16,0x1fa27cf8)
d=HH(b,c,d,a,M2,23,0xc4ac5665)
第四轮
a=II(a,b,c,d,M0,6,0xf4292244)
b=II(d,a,b,c,M7,10,0x432aff97)
c=II(c,d,a,b,M14,15,0xab9423a7)
d=II(b,c,d,a,M5,21,0xfc93a039)
a=II(a,b,c,d,M12,6,0x655b59c3)
b=II(d,a,b,c,M3,10,0x8f0ccc92)
c=II(c,d,a,b,M10,15,0xffeff47d)
d=II(b,c,d,a,M1,21,0x85845dd1)
a=II(a,b,c,d,M8,6,0x6fa87e4f)
b=II(d,a,b,c,M15,10,0xfe2ce6e0)
c=II(c,d,a,b,M6,15,0xa3014314)
d=II(b,c,d,a,M13,21,0x4e0811a1)
a=II(a,b,c,d,M4,6,0xf7537e82)
b=II(d,a,b,c,M11,10,0xbd3af235)
c=II(c,d,a,b,M2,15,0x2ad7d2bb)
d=II(b,c,d,a,M9,21,0xeb86d391)
5)每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环。
如果上面的过程用JAVA代码来实现的话,代码如下:





























































































































































































































































































































































































普遍认为MD5是很安全,因为暴力破解的时间是一般人无法接受的。实际上如果把用户的密码MD5处理后再存储到数据库,其实是很不安全的。因为用户的密码是比较短的,而且很多用户的密码都使用生日,手机号码,身份证号码,电话号码等等。或者使用常用的一些吉利的数字,或者某个英文单词。如果我把常用的密码先MD5处理,把数据存储起来,然后再跟你的MD5结果匹配,这时我就有可能得到明文。比如某个MD5破解网站http://www.cmd5.com/default.aspx,我把其网站下的公告复制如下
md5破解、动网论坛密码破解等不再需要用穷举法,本站共有md5记录235亿条,还在不断增长中,已包含10位及10位以下数字、7位字母、部分7位字母+数字,全部6位及以下字母加数字等组合,并针对国内用户做了大量优化,例如已经包含所有手机号码、全国部分大中城市固定电话号码、百家姓、常用拼音等大量组合,另加入了某大型网站真实会员密码数据10万条。本站数据量大,查询速度快,同时支持16位及32位密码查询。通过对10万会员的真实动网论坛样本数据的测试,本站对于动网论坛密码的命中率达到83%。
本站4T的硬盘已经上线,正在生成数据,预计需要2个月左右时间,到时候本站能查询到12位数字和9位字母。
你可以用你的生日,手机号码去测试一下。本站4T的硬盘已经上线,正在生成数据,预计需要2个月左右时间,到时候本站能查询到12位数字和9位字母。
我觉得只需要将上面我写的MD5的标准幻数A,B,C,D的值修改一下,修改后也不是MD5算法了,因为不能保证唯一性。这样就算别人得到32位的值,他如果不知道幻数的值是无法还原明文的。就算得到了幻数,也是很难破解的。
JAVA实现MD5
在java中实现MD5是很简单的,在包java.security有个类MessageDigest。官方文档如下
MessageDigest类为应用程序提供信息摘要算法的功能,如MD5或SHA算法。信息摘要是安全的单向哈希函数,它接收任意大小的数据,输出固定长度的哈希值。
MessageDigest对象开始被初始化。该对象通过使用update方法处理数据。任何时候都可以调用reset方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用digest方法之一完成哈希计算。
对于给定数量的更新数据,digest方法只能被调用一次。digest被调用后,MessageDigest对象被重新设置成其初始状态。
使用MessageDigest很简单,例如
MessageDigest对象开始被初始化。该对象通过使用update方法处理数据。任何时候都可以调用reset方法重置摘要。一旦所有需要更新的数据都已经被更新了,应该调用digest方法之一完成哈希计算。
对于给定数量的更新数据,digest方法只能被调用一次。digest被调用后,MessageDigest对象被重新设置成其初始状态。


















































1)JS版的MD5(调用方法:md5(明文))











































































































































































































































































相关推荐
总结来说,MATLAB实现MD5算法涉及的主要知识点包括:MD5算法的背景和用途,哈希函数的基本概念,MD5算法的四轮循环结构,FF、GG、HH、II四个非线性函数的作用,以及MATLAB中位运算和数组操作的应用。通过学习这个...
MD5算法封装DLL是指将MD5算法封装到动态链接库(DLL)文件中,供其他程序调用。DLL是一种可重用代码的模块,它可以包含执行特定任务的函数或其他可执行代码。通过这种方式,开发人员无需在每个项目中实现MD5算法,...
1. **MD5算法原理**:MD5算法通过四轮不同的操作(分别是Additive-XOR、Rotational、Additive和Parity)对输入数据进行处理,每轮操作都包含多个步骤,最终得到一个128位的摘要。这个摘要可以视为输入数据的“数字...
这对于快速实现MD5计算功能非常方便,尤其适合那些不熟悉MD5算法底层实现的开发者。 Borland C++ Builder(简称BCB)是Embarcadero Technologies开发的一款集成开发环境,主要用于编写C++应用程序。Bcb6是其第六个...
### MD5算法详解 #### 一、概述 MD5(Message-Digest Algorithm 5)是一种广泛使用的散列函数,能够将任意长度的消息压缩成一个固定长度(128位)的散列值,通常用于数据完整性的校验、密码存储等场景。MD5算法的...
### MD5算法详解 #### 一、MD5算法概述 MD5(Message-Digest Algorithm 5)是一种广泛使用的散列函数,它可以将任意长度的消息转换成一个固定长度的散列值,通常用来验证数据的完整性。MD5算法的核心在于它能够快速...
然而,需要注意的是,MD5算法虽然高效且实用,但由于存在碰撞攻击的可能性(即不同的输入可能会得到相同的MD5摘要),所以在安全性要求较高的场景,MD5已经逐渐被SHA-256等更安全的哈希算法所取代。 在使用"基于MD5...
总的来说,C语言实现的MD5算法在STM32单片机上的应用,需要对C语言编程、嵌入式系统开发以及MD5算法本身有深入理解。通过 lwIP协议栈中的MD5功能,可以增强系统的安全性和可靠性,特别是在网络通信和数据保护方面。
MD5算法是一种广泛使用的 Hash 算法,常用于确保信息传输的完整性与一致性。对于输入的任一不定长度信息, MD5算法在对最后一块进行填充后用512个比特对其进行分组,使用压缩函数将其生成4个32比特的数据,合并为128...
MD5 算法详解及 Java 实现 在信息安全领域中,MD5 算法是一种常用的摘要算法,用于生成信息的数字指纹。MD5 全称为 Message-Digest Algorithm 5,即信息-摘要算法 5。它可以将任意长度的信息转换为一个固定长度的...
在本项目中,"md5算法实例"可能是实现了一个简单的MD5计算功能,用户可以通过输入任何值,程序会返回这个值经过MD5算法处理后的哈希结果。这样的实例通常涉及以下编程知识点: 1. **哈希函数**:理解哈希函数的基本...
文件完整性检查工具,如"MD5 Checksum Verifier v3.9-CRD",是利用MD5算法来验证文件是否保持原样的实用程序。它的工作原理是先计算原始文件的MD5哈希值,然后在文件传输或操作后再次计算该值,对比两次哈希值是否...
标题中的“MD5ppt下载”可能指的是包含MD5算法讲解的PPT教学材料,这种材料通常会深入浅出地介绍MD5的工作原理、计算过程以及其在实际中的应用。在描述中提到“与学校老师教学PPT上的讲解有所更改”,这可能意味着这...
### MD5算法在Java中的实现 #### 一、概述 MD5(Message-Digest Algorithm 5)是一种广泛使用的散列函数,它能够将任意长度的数据转换为一个固定长度(通常是128位)的十六进制字符串。由于其计算速度快且结果不...
2. **编写MD5头文件(Md5.h)**:这个头文件通常包含MD5算法的结构体定义,如MD5_CTX,用于存储中间计算结果。还会声明MD5的初始化函数(如MD5_Init)、更新函数(如MD5_Update)和最终化函数(如MD5_Final),它们...
在提供的压缩包文件"MD5算法"中,可能包含了实现MD5算法的C语言源代码、测试用例、以及可能的算法分析文档。通过阅读和理解这些文件,你可以深入学习MD5算法的实现细节,并且能够应用到实际项目中,如数据完整性校验...
在学习MD5算法时,可以参考提供的"MD5算法代码及测试参考"文件。这份文件可能包含了MD5算法的实现,可能是用某种编程语言如Python、Java或C++编写。通过阅读和理解代码,你可以了解MD5的具体计算过程,包括如何将...
在提供的文件列表中,`md5.cpp`和`test.cpp`可能是实现MD5算法的源代码,`md5lib.h`可能是包含MD5函数声明的头文件,而`md5.h`可能包含了更具体的MD5实现细节或相关辅助函数。`md5.rar`是一个压缩文件,可能包含了...
### MD5算法与数字签名 #### 一、引言 随着互联网技术的飞速发展,信息安全问题日益凸显,其中信息的完整性保护变得尤为重要。传统的加密技术、访问控制技术和认证技术等虽能有效防止未授权访问,但对于信息一旦被...