⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 md5的介绍,算法和实现.htm

📁 MD5算法的相关资料
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0047)http://www.pediy.com/bbshtml/BBS4/kanxue202.htm -->
<HTML><HEAD><TITLE>MD5的介绍,算法和实现</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<STYLE type=text/css></STYLE>
<LINK href="MD5的介绍,算法和实现.files/css.css" type=text/css rel=stylesheet>
<META content="MSHTML 5.50.4134.100" name=GENERATOR></HEAD>
<BODY class=p9 bgColor=#ffffff background=MD5的介绍,算法和实现.files/back.gif><FONT 
color=blue>标 题:</FONT>MD5的介绍,算法和实现。 ————娃娃/[CCG] (23千字)<BR><FONT 
color=blue>发信人:</FONT>1212<BR><FONT color=blue>时 间:</FONT>2001-11-4 14:36:12 
<BR><FONT color=blue>详细信息:</FONT><BR>
<BLOCKQUOTE>MD5的介绍,算法和实现 <BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Wrote By 娃娃/[CCG] 
  <BR><BR><BR><BR>最近对各种加密算法很感兴趣 
  原因有好多:破解TMG的KeyGenme失败;羡慕伪哥的万象注册机;佩服夜月大哥和Stkman大哥的密码学功力………… 
  偶然间跟Stkman大哥谈起来MD5,他给了我很多帮助 使得我可以写出这篇文章。 <BR><BR>MD5简介: 
  <BR><BR>MD5的全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data 
  Security Inc发明,经MD2、MD3和MD4发展而来。 
  <BR><BR>Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了“字节串”而不是“字符串”这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。 
  <BR><BR>MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,(我刚开始还愚蠢的认为MD5是可逆的算法 
  感谢Stkman大哥的讲解)换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。 
  <BR><BR>MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。 
  <BR><BR>MD5还广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的, 
  用户Login的时候,系统是把用户输入的密码计算成MD5值,然后再去和系统中保存的MD5值进行比较,而系统并不“知道”用户的密码是什么。 
  <BR><BR>一些黑客破获这种密码的方法是一种被称为“跑字典”的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。 
  <BR><BR>即使假设密码的最大长度为8,同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是P(62,1)+P(62,2)….+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要TB级的磁盘组,而且这种方法还有一个前提,就是能获得目标账户的密码MD5值的情况下才可以。 
  <BR><BR>在软件的加密保护中 很多软件采用MD5保护&nbsp; 但是由于MD5算法为不可逆算法 
  所以所有的软件都是使用MD5算法作为一个加密的中间步骤,比如对用户名做一个MD5变换,结果再进行一个可逆的加密变换,做注册机时也只要先用MD5变换,然后再用一个逆算法。所以对于破解者来说只要能看出是MD5就很容易了。 
  <BR><BR>MD5代码的特点明显,跟踪时很容易发现,如果软件采用MD5算法,在数据初始化的时候必然用到以下的四个常数 <BR>0x67452301; 
  <BR>0xefcdab89; <BR>0x98badcfe; <BR>0x10325476; <BR>若常数不等 则可能是变形的MD5算法 
  或者根本就不是这个算法。在内存了也就是 <BR>01 23 45 67 89 ab cd ef fe dc ......32 10&nbsp; &nbsp; 
  16个字节 <BR>———————————————————————————————————————————— <BR><BR>MD5算法: 
  <BR><BR>第一步:增加填充 
  <BR>增加padding使得数据长度(bit为单位)模512为448。如果数据长度正好是模512为448,增加512个填充bit,也就是说填充的个数为1-512。第一个bit为1,其余全部为0。 
  <BR>第二步:补足长度 
  <BR>将数据长度转换为64bit的数值,如果长度超过64bit所能表示的数据长度的范围,值保留最后64bit,增加到前面填充的数据后面,使得最后的数据为512bit的整数倍。也就是32bit的16倍的整数倍。在RFC1321中,32bit称为一个word。 
  <BR>第三步:初始化变量: <BR>用到4个变量,分别为A、B、C、D,均为32bit长。初始化为: <BR>A: 01 23 45 67 <BR>B: 
  89 ab cd ef <BR>C: fe dc ba 98 <BR>D: 76 54 32 10 <BR>第四步:数据处理: 
  <BR>首先定义4个辅助函数: <BR>F(X,Y,Z) = XY v not(X) Z <BR>G(X,Y,Z) = XZ v Y not(Z) 
  <BR>H(X,Y,Z) = X xor Y xor Z <BR>I(X,Y,Z) = Y xor (X v not(Z)) 
  <BR>其中:XY表示按位与,X v Y表示按位或,not(X)表示按位取反。xor表示按位异或。 <BR>函数中的X、Y、Z均为32bit。 
  <BR><BR>定义一个需要用到的数组:T(i),i取值1-64,T(i)等于abs(sin(i))的4294967296倍的整数部分,i为弧度。 
  <BR>假设前三步处理后的数据长度为32*16*Nbit <BR><BR>第五步:输出: 
  <BR>最后得到的ABCD为输出结果,共128bit。A为低位,D为高位。 <BR><BR><BR><BR><BR><BR>MD5在编程中的实现 
  <BR><BR><BR>下面来看看如何在C语言和VB中实现MD5算法 
  <BR>———————————————————————————————————————————— <BR><BR>*/ <BR>#ifndef 
  PROTOTYPES <BR>#define PROTOTYPES 0 <BR>#endif <BR>typedef unsigned char 
  *POINTER; <BR>typedef unsigned short int UINT2; <BR>typedef unsigned long int 
  UINT4; <BR>#if PROTOTYPES <BR>#define PROTO_LIST(list) list <BR>#else 
  <BR>#define PROTO_LIST(list) () <BR>#endif <BR><BR>—————————— 
  MD5.h———————————————————————————— <BR><BR>typedef struct { <BR>&nbsp; UINT4 
  state[4];&nbsp; &nbsp; &nbsp; &nbsp; <BR>&nbsp; UINT4 count[2];&nbsp; &nbsp; 
  &nbsp; <BR>&nbsp; unsigned char buffer[64];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>} MD5_CTX; <BR><BR>void MD5Init 
  PROTO_LIST ((MD5_CTX *)); <BR>void MD5Update PROTO_LIST <BR>&nbsp; ((MD5_CTX 
  *, unsigned char *, unsigned int)); <BR>void MD5Final PROTO_LIST ((unsigned 
  char [16], MD5_CTX *)); <BR><BR>※※※※※※※※※MD5C.C※※※※※※※※※※※※※※※※※※※※※※※※ 
  <BR>#include "global.h" <BR>#include "md5.h" <BR>#define S11 7 <BR>#define S12 
  12 <BR>#define S13 17 <BR>#define S14 22 <BR>#define S21 5 <BR>#define S22 9 
  <BR>#define S23 14 <BR>#define S24 20 <BR>#define S31 4 <BR>#define S32 11 
  <BR>#define S33 16 <BR>#define S34 23 <BR>#define S41 6 <BR>#define S42 10 
  <BR>#define S43 15 <BR>#define S44 21 <BR><BR>static void MD5Transform 
  PROTO_LIST ((UINT4 [4], unsigned char [64])); <BR>static void Encode 
  PROTO_LIST <BR>&nbsp; ((unsigned char *, UINT4 *, unsigned int)); <BR>static 
  void Decode PROTO_LIST <BR>&nbsp; ((UINT4 *, unsigned char *, unsigned int)); 
  <BR>static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); 
  <BR>static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); 
  <BR><BR>static unsigned char PADDING[64] = { <BR>&nbsp; 0x80, 0, 0, 0, 0, 0, 
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <BR>&nbsp; 0, 0, 0, 0, 0, 0, 
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <BR>&nbsp; 0, 0, 0, 0, 0, 
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 <BR>}; <BR><BR>/* 定义F G H I 为四个基数 
  <BR><BR>#define F(x, y, z) (((x) &amp; (y)) | ((~x) &amp; (z))) <BR>#define 
  G(x, y, z) (((x) &amp; (z)) | ((y) &amp; (~z))) <BR>#define H(x, y, z) ((x) ^ 
  (y) ^ (z)) <BR>#define I(x, y, z) ((y) ^ ((x) | (~z))) <BR>#define 
  ROTATE_LEFT(x, n) (((x) &lt;&lt; (n)) | ((x) &gt;&gt; (32-(n)))) <BR>#define 
  FF(a, b, c, d, x, s, ac) { \ <BR>(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); 
  \ <BR>(a) = ROTATE_LEFT ((a), (s)); \ <BR>(a) += (b); \ <BR>&nbsp; } 
  <BR>#define GG(a, b, c, d, x, s, ac) { \ <BR>(a) += G ((b), (c), (d)) + (x) + 
  (UINT4)(ac); \ <BR>(a) = ROTATE_LEFT ((a), (s)); \ <BR>(a) += (b); \ 
  <BR>&nbsp; } <BR>#define HH(a, b, c, d, x, s, ac) { \ <BR>(a) += H ((b), (c), 
  (d)) + (x) + (UINT4)(ac); \ <BR>(a) = ROTATE_LEFT ((a), (s)); \ <BR>(a) += 
  (b); \ <BR>&nbsp; } <BR>#define II(a, b, c, d, x, s, ac) { \ <BR>(a) += I 
  ((b), (c), (d)) + (x) + (UINT4)(ac); \ <BR>(a) = ROTATE_LEFT ((a), (s)); \ 
  <BR>(a) += (b); \ <BR>&nbsp; } <BR><BR>/*开始进行MD5计算 <BR>void MD5Init (context) 
  <BR>MD5_CTX *context;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>{ <BR>&nbsp; 
  context-&gt;count[0] = context-&gt;count[1] = 0; <BR>&nbsp; /* 
  在这里定义四个常数,也就是我们刚才讲到的四个特征数. <BR><BR>&nbsp; context-&gt;state[0] = 0x67452301; 
  <BR>&nbsp; context-&gt;state[1] = 0xefcdab89; <BR>&nbsp; context-&gt;state[2] 
  = 0x98badcfe; <BR>&nbsp; context-&gt;state[3] = 0x10325476; <BR>} <BR><BR>void 
  MD5Update (context, input, inputLen) <BR>MD5_CTX *context;&nbsp; &nbsp; &nbsp; 
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
  &nbsp; &nbsp; <BR>unsigned char *input;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>unsigned 
  int inputLen;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
  <BR>{ <BR>&nbsp; unsigned int i, index, partLen; <BR><BR>&nbsp; index = 
  (unsigned int)((context-&gt;count[0] &gt;&gt; 3) &amp; 0x3F); <BR><BR>&nbsp; 
  if ((context-&gt;count[0] += ((UINT4)inputLen &lt;&lt; 3)) &lt; 
  ((UINT4)inputLen &lt;&lt; 3)) <BR>context-&gt;count[1]++; <BR>&nbsp; 
  context-&gt;count[1] += ((UINT4)inputLen &gt;&gt; 29); <BR><BR>&nbsp; partLen 
  = 64 - index; <BR><BR>&nbsp; if (inputLen &gt;= partLen) { <BR>MD5_memcpy 
  <BR>&nbsp; ((POINTER)&amp;context-&gt;buffer[index], (POINTER)input, partLen); 
  <BR>MD5Transform (context-&gt;state, context-&gt;buffer); <BR><BR>for (i = 
  partLen; i + 63 &lt; inputLen; i += 64) <BR>&nbsp; MD5Transform 
  (context-&gt;state, &amp;input[i]); <BR><BR>index = 0; <BR>&nbsp; } <BR>&nbsp; 
  else <BR>i = 0; <BR><BR>&nbsp; MD5_memcpy 
  <BR>((POINTER)&amp;context-&gt;buffer[index], (POINTER)&amp;input[i], 
  <BR>&nbsp; inputLen-i); <BR>} <BR><BR>void MD5Final (digest, context) 
  <BR>unsigned char digest[16];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
  &nbsp; &nbsp; <BR>MD5_CTX *context;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <BR>{ 
  <BR>&nbsp; unsigned char bits[8]; <BR>&nbsp; unsigned int index, padLen; 
  <BR><BR>&nbsp; Encode (bits, context-&gt;count, 8); <BR><BR>&nbsp; index = 
  (unsigned int)((context-&gt;count[0] &gt;&gt; 3) &amp; 0x3f); <BR>&nbsp; 
  padLen = (index &lt; 56) ? (56 - index) : (120 - index); <BR>&nbsp; MD5Update 
  (context, PADDING, padLen); <BR>&nbsp; MD5Update (context, bits, 8); 
  <BR><BR>&nbsp; Encode (digest, context-&gt;state, 16); <BR>&nbsp; MD5_memset 
  ((POINTER)context, 0, sizeof (*context)); <BR>} <BR><BR>static void 
  MD5Transform (state, block) <BR>UINT4 state[4]; <BR>unsigned char block[64]; 
  <BR>{ <BR>&nbsp; UINT4 a = state[0], b = state[1], c = state[2], d = state[3], 
  x[16]; <BR><BR>&nbsp; Decode (x, block, 64); <BR><BR>&nbsp; /* 第一轮循环 */ 
  <BR>&nbsp; FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ <BR>&nbsp; FF (d, 
  a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ <BR>&nbsp; FF (c, d, a, b, x[ 2], 
  S13, 0x242070db); /* 3 */ <BR>&nbsp; FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); 
  /* 4 */ <BR>&nbsp; FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ <BR>&nbsp; 
  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ <BR>&nbsp; FF (c, d, a, b, x[ 
  6], S13, 0xa8304613); /* 7 */ <BR>&nbsp; FF (b, c, d, a, x[ 7], S14, 
  0xfd469501); /* 8 */ <BR>&nbsp; FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 
  */ <BR>&nbsp; FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ <BR>&nbsp; FF 
  (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ <BR>&nbsp; FF (b, c, d, a, 
  x[11], S14, 0x895cd7be); /* 12 */ <BR>&nbsp; FF (a, b, c, d, x[12], S11, 
  0x6b901122); /* 13 */ <BR>&nbsp; FF (d, a, b, c, x[13], S12, 0xfd987193); /* 
  14 */ <BR>&nbsp; FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ <BR>&nbsp; 
  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ <BR><BR>/* 第二轮循环 */ 
  <BR>&nbsp; GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ <BR>&nbsp; GG (d, 
  a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ <BR>&nbsp; GG (c, d, a, b, x[11], 
  S23, 0x265e5a51); /* 19 */ <BR>&nbsp; GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -