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

📄 md5的介绍,算法和实现(娃娃).txt

📁 md5加密算法
💻 TXT
📖 第 1 页 / 共 2 页
字号:
标 题:MD5的介绍,算法和实现。 ————娃娃/[CCG] (23千字)
发信人:1212
时 间:2001-11-4 14:36:12 
详细信息:

MD5的介绍,算法和实现 
                          Wrote By 娃娃/[CCG] 



最近对各种加密算法很感兴趣 原因有好多:破解TMG的KeyGenme失败;羡慕伪哥的万象注册机;佩服夜月大哥和Stkman大哥的密码学功力………… 偶然间跟Stkman大哥谈起来MD5,他给了我很多帮助 使得我可以写出这篇文章。 

MD5简介: 

MD5的全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经MD2、MD3和MD4发展而来。 

Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了“字节串”而不是“字符串”这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。 

MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,(我刚开始还愚蠢的认为MD5是可逆的算法 感谢Stkman大哥的讲解)换句话说就是,即使你看到源程序和算法描述,也无法将一个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值的情况下才可以。 

在软件的加密保护中 很多软件采用MD5保护  但是由于MD5算法为不可逆算法 所以所有的软件都是使用MD5算法作为一个加密的中间步骤,比如对用户名做一个MD5变换,结果再进行一个可逆的加密变换,做注册机时也只要先用MD5变换,然后再用一个逆算法。所以对于破解者来说只要能看出是MD5就很容易了。 

MD5代码的特点明显,跟踪时很容易发现,如果软件采用MD5算法,在数据初始化的时候必然用到以下的四个常数 
0x67452301; 
0xefcdab89; 
0x98badcfe; 
0x10325476; 
若常数不等 则可能是变形的MD5算法 或者根本就不是这个算法。在内存了也就是 
01 23 45 67 89 ab cd ef fe dc ......32 10    16个字节 
———————————————————————————————————————————— 

MD5算法: 

第一步:增加填充 
增加padding使得数据长度(bit为单位)模512为448。如果数据长度正好是模512为448,增加512个填充bit,也就是说填充的个数为1-512。第一个bit为1,其余全部为0。 
第二步:补足长度 
将数据长度转换为64bit的数值,如果长度超过64bit所能表示的数据长度的范围,值保留最后64bit,增加到前面填充的数据后面,使得最后的数据为512bit的整数倍。也就是32bit的16倍的整数倍。在RFC1321中,32bit称为一个word。 
第三步:初始化变量: 
用到4个变量,分别为A、B、C、D,均为32bit长。初始化为: 
A: 01 23 45 67 
B: 89 ab cd ef 
C: fe dc ba 98 
D: 76 54 32 10 
第四步:数据处理: 
首先定义4个辅助函数: 
F(X,Y,Z) = XY v not(X) Z 
G(X,Y,Z) = XZ v Y not(Z) 
H(X,Y,Z) = X xor Y xor Z 
I(X,Y,Z) = Y xor (X v not(Z)) 
其中:XY表示按位与,X v Y表示按位或,not(X)表示按位取反。xor表示按位异或。 
函数中的X、Y、Z均为32bit。 

定义一个需要用到的数组:T(i),i取值1-64,T(i)等于abs(sin(i))的4294967296倍的整数部分,i为弧度。 
假设前三步处理后的数据长度为32*16*Nbit 

第五步:输出: 
最后得到的ABCD为输出结果,共128bit。A为低位,D为高位。 





MD5在编程中的实现 


下面来看看如何在C语言和VB中实现MD5算法 
———————————————————————————————————————————— 

*/ 
#ifndef PROTOTYPES 
#define PROTOTYPES 0 
#endif 
typedef unsigned char *POINTER; 
typedef unsigned short int UINT2; 
typedef unsigned long int UINT4; 
#if PROTOTYPES 
#define PROTO_LIST(list) list 
#else 
#define PROTO_LIST(list) () 
#endif 

—————————— MD5.h———————————————————————————— 

typedef struct { 
  UINT4 state[4];        
  UINT4 count[2];      
  unsigned char buffer[64];                      
} MD5_CTX; 

void MD5Init PROTO_LIST ((MD5_CTX *)); 
void MD5Update PROTO_LIST 
  ((MD5_CTX *, unsigned char *, unsigned int)); 
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); 

※※※※※※※※※MD5C.C※※※※※※※※※※※※※※※※※※※※※※※※ 
#include "global.h" 
#include "md5.h" 
#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 
#define S43 15 
#define S44 21 

static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); 
static void Encode PROTO_LIST 
  ((unsigned char *, UINT4 *, unsigned int)); 
static void Decode PROTO_LIST 
  ((UINT4 *, unsigned char *, unsigned int)); 
static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); 
static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); 

static unsigned char PADDING[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 
}; 

/* 定义F G H I 为四个基数 

#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 ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 
#define FF(a, b, c, d, x, s, ac) { \ 
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ 
(a) = ROTATE_LEFT ((a), (s)); \ 
(a) += (b); \ 
  } 
#define GG(a, b, c, d, x, s, ac) { \ 
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ 
(a) = ROTATE_LEFT ((a), (s)); \ 
(a) += (b); \ 
  } 
#define HH(a, b, c, d, x, s, ac) { \ 
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ 
(a) = ROTATE_LEFT ((a), (s)); \ 
(a) += (b); \ 
  } 
#define II(a, b, c, d, x, s, ac) { \ 
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ 
(a) = ROTATE_LEFT ((a), (s)); \ 
(a) += (b); \ 
  } 

/*开始进行MD5计算 
void MD5Init (context) 
MD5_CTX *context;                              
{ 
  context->count[0] = context->count[1] = 0; 
  /* 在这里定义四个常数,也就是我们刚才讲到的四个特征数. 

  context->state[0] = 0x67452301; 
  context->state[1] = 0xefcdab89; 
  context->state[2] = 0x98badcfe; 
  context->state[3] = 0x10325476; 
} 

void MD5Update (context, input, inputLen) 
MD5_CTX *context;                                
unsigned char *input;                            
unsigned int inputLen;                  
{ 
  unsigned int i, index, partLen; 

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

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

  partLen = 64 - index; 

  if (inputLen >= partLen) { 
MD5_memcpy 
  ((POINTER)&context->buffer[index], (POINTER)input, partLen); 
MD5Transform (context->state, context->buffer); 

for (i = partLen; i + 63 < inputLen; i += 64) 
  MD5Transform (context->state, &input[i]); 

index = 0; 
  } 
  else 
i = 0; 

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

void MD5Final (digest, context) 
unsigned char digest[16];                  
MD5_CTX *context;                              
{ 
  unsigned char bits[8]; 
  unsigned int index, padLen; 

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

  index = (unsigned int)((context->count[0] >> 3) & 0x3f); 
  padLen = (index < 56) ? (56 - index) : (120 - index); 
  MD5Update (context, PADDING, padLen); 
  MD5Update (context, bits, 8); 

  Encode (digest, context->state, 16); 
  MD5_memset ((POINTER)context, 0, sizeof (*context)); 
} 

static void MD5Transform (state, block) 
UINT4 state[4]; 
unsigned char block[64]; 
{ 
  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 

  Decode (x, block, 64); 

  /* 第一轮循环 */ 
  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 */ 

/* 第二轮循环 */ 
  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 (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ 
  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 */ 

  /* 第三轮循环 */ 
  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 */ 

  /* 第四轮循环 */ 
  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 (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 
  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; 

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

} 
static void Encode (output, input, len) 
unsigned char *output; 
UINT4 *input; 
unsigned int len; 
{ 
  unsigned int i, j; 

  for (i = 0, j = 0; j < len; i++, j += 4) { 
output[j] = (unsigned char)(input[i] & 0xff); 
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 
  } 
} 

static void Decode (output, input, len) 
UINT4 *output; 
unsigned char *input; 
unsigned int len; 
{ 
  unsigned int i, j; 

  for (i = 0, j = 0; j < len; i++, j += 4) 
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | 
  (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); 
} 

static void MD5_memcpy (output, input, len) 
POINTER output; 
POINTER input; 
unsigned int len; 
{ 
  unsigned int i; 

⌨️ 快捷键说明

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