[转]MD5简介

MD5
目录· MD5简介
· 算法的应用
· 算法描述
· 具体的一个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中有详细的描述( http://www.ietf.org/rfc/rfc1321.txt),这是一份最权威的文档,由ronald l. rivest在1992年8月向ieft提交。

  rivest在1989年开发出md2算法。在这个算法中,首先对信息进行数据补位,使信息的字节长度是16的倍数。然后,以一个16位的检验和追加到信息末尾。并且根据这个新产生的信息计算出散列值。后来,rogier和chauvaud发现如果忽略了检验和将产生md2冲突。md2算法的加密后结果是唯一的--既没有重复。

  为了加强算法的安全性,rivest在1990年又开发出md4算法。md4算法同样需要填补信息以确保信息的字节长度加上448后能被512整除(信息字节长度mod 512 = 448)。然后,一个以64位二进制表示的信息的最初长度被添加进来。信息被处理成512位damg?rd/merkle迭代结构的区块,而且每个区块要通过三个不同步骤的处理。den boer和bosselaers以及其他人很快的发现了攻击md4版本中第一步和第三步的漏洞。dobbertin向大家演示了如何利用一部普通的个人电脑在几分钟内找到md4完整版本中的冲突(这个冲突实际上是一种漏洞,它将导致对不同的内容进行加密却可能得到相同的加密后结果)。毫无疑问,md4就此被淘汰掉了。

  尽管md4算法在安全上有个这么大的漏洞,但它对在其后才被开发出来的好几种信息安全加密算法的出现却有着不可忽视的引导作用。除了md5以外,其中比较有名的还有sha-1、ripe-md以及haval等。

  一年以后,即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冲突的机器(这台机器在1994年的制造成本大约是一百万美元)可以平均每24天就找到一个冲突。但单从1991年到2001年这10年间,竟没有出现替代md5算法的md6或被叫做其他什么名字的新算法这一点,我们就可以看出这个瑕疵并没有太多的影响md5的安全性。上面所有这些都不足以成为md5的在实际应用中的问题。并且,由于md5算法的使用不需要支付任何版权费用的,所以在一般的情况下(非绝密应用领域。但即便是应用在绝密领域内,md5也不失为一种非常优秀的中间技术),md5怎么都应该算得上是非常安全的了。

  2004年8月17日的美国加州圣巴巴拉的国际密码学会议(Crypto’2004)上,来自中国山东大学的王小云教授做了破译MD5、HAVAL-128、 MD4和RIPEMD算法的报告,公布了MD系列算法的破解结果。宣告了固若金汤的世界通行密码标准MD5的堡垒轰然倒塌,引发了密码学界的轩然大波。

  MD5破解工程权威网站 http://www.md5crk.com/ 是为了公开征集专门针对MD5的攻击而设立的,网站于2004年8月17日宣布:“中国研究人员发现了完整MD5算法的碰撞;Wang, Feng, Lai与Yu公布了MD5、MD4、HAVAL-128、RIPEMD-128几个 Hash函数的碰撞。这是近年来密码学领域最具实质性的研究进展。使用他们的技术,在数个小时内就可以找到MD5碰撞。……由于这个里程碑式的发现,MD5CRK项目将在随后48小时内结束”。

MD5用的是哈希函数,在计算机网络中应用较多的不可逆加密算法有RSA公司发明的MD5算法和由美国国家技术标准研究所建议的安全散列算法SHA.

算法的应用


  MD5的典型应用是对一段信息(Message)产生信息摘要(Message-Digest),以防止被篡改。比如,在UNIX下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如:

   MD5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461

  这就是tanajiya.tar.gz文件的数字签名。MD5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的MD5信息摘要。为了让读者朋友对MD5的应用有个直观的认识,笔者以一个比方和一个实例来简要描述一下其工作过程:
大家都知道,地球上任何人都有自己独一无二的指纹,这常常成为公安机关鉴别罪犯身份最值得信赖的方法;与之类似,MD5就可以为任何文件(不管其大小、格式、数量)产生一个同样独一无二的“数字指纹”,如果任何人对文件做了任何改动,其MD5值也就是对应的“数字指纹”都会发生变化。
我们常常在某些软件下载站点的某软件信息中看到其MD5值,它的作用就在于我们可以在下载该软件后,对下载回来的文件用专门的软件(如Windows MD5 Check等)做一次MD5校验,以确保我们获得的文件与该站点提供的文件为同一文件。利用MD5算法来进行文件校验的方案被大量应用到软件下载站、论坛数据库、系统文件安全等方面。
  MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现(两个MD5值不相同)。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。
  所以,要遇到了md5密码的问题,比较好的办法是:你可以用这个系统中的md5()函数重新设一个密码,如admin,把生成的一串密码覆盖原来的就行了。

  MD5还广泛用于加密解密技术上,如Unix、各类BSD系统登录密码(在MD5诞生前采用的是DES加密算法,后因MD5安全性更高,DES被淘汰)、通信信息加密(如大家熟悉的即时通信软件MyIM)、数字签名等诸多方。比如在UNIX系统中用户的密码就是以MD5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成MD5值,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。所以,要遇到了md5密码的问题,比较好的办法是:你可以用这个系统中的md5()函数重新设一个密码,如admin,把生成的一串密码覆盖原来的就行了。



  正是因为这个原因,现在被黑客使用最多的一种破译密码的方法就是一种被称为"跑字典"的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。我们假设密码的最大长度为8位字节(8 Bytes),同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是P(62,1)+P(62,2)….+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要TB级的磁盘阵列,而且这种方法还有一个前提,就是能获得目标账户的密码MD5值的情况下才可以。这种加密技术被广泛的应用于UNIX系统中,这也是为什么UNIX系统比一般操作系统更为坚固一个重要原因。

  
算法描述


  对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实现
=============================头文件Security.h===============================================

/*
使用方法:

char Md5Buffer[33];
CSecurity Security;
Security.MD5("a string",Md5Buffer);

执行完成之后Md5Buffer中即存储了由"a string"计算得到的MD5值

*/

// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 SECURITY_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// SECURITY_API 函数视为是从此 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。

//在使用该类的地方包含本文件即可
#ifdef SECURITY_EXPORTS
#define SECURITY_API __declspec(dllexport)
#else
#define SECURITY_API __declspec(dllimport)
#endif

/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;

/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;

/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;

#define PROTO_LIST(list) list

/* MD5 context. */
typedef struct _MD5_CTX
{
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;

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
};
/* 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
#define S43 15
#define S44 21

/* F, G, H and I are basic MD5 functions.
*/
#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)))

/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#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); }

#define TEST_BLOCK_LEN 1000
#define TEST_BLOCK_COUNT 1000

// 此类是从 Security.dll 导出的
class SECURITY_API CSecurity
{
public:
CSecurity(void);
void CSecurity::MD5( const char *string ,char *lpMD5StringBuffer ) ;
private:
  void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
  void MD5_memcpy PROTO_LIST ((POINTER, POINTER, size_t));
  void MD5_memset PROTO_LIST ((POINTER, int, size_t));
  void MD5Init PROTO_LIST ((MD5_CTX *));
  void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, size_t));
  void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
  void MDTimeTrial PROTO_LIST ((void));
  void StringAddOne PROTO_LIST ((char *));
  void Encode PROTO_LIST ((unsigned char *, UINT4 *, size_t));
  void Decode PROTO_LIST ((UINT4 *, unsigned char *, size_t));
};
===============================Security.cpp====================================================

// Security.cpp : 定义 DLL 应用程序的入口点。
//

#include "stdafx.h"

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<ctype.h>

#include "Security.h"

BOOL APIENTRY DllMain( HANDLE hModule,
       DWORD  ul_reason_for_call,
       LPVOID lpReserved
       )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
  break;
}
    return TRUE;
}


// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 Security.h
CSecurity::CSecurity()
{
return;
}


/*
MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void CSecurity::MD5Init( MD5_CTX *context )
{
context->count[0] = context->count[1] = 0;
/*
Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}

/*
MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void CSecurity::MD5Update(
       MD5_CTX *context, /* context */
       unsigned char *input, /* input block */
       size_t inputLen /* length of input block */
       )
{
size_t i, index, partLen;

/* Compute number of bytes mod 64 */
index = (size_t)((context->count[0] >> 3) & 0x3F);

/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
  < ((UINT4)inputLen << 3))
  context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);

partLen = 64 - index;

/* Transform as many times as possible. */
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 );
  
  index = 0;
}
else
  i = 0;

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

/*
MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void CSecurity::MD5Final(
      unsigned char digest[16], /* message digest */
      MD5_CTX *context /* context */
      )
{
unsigned char bits[8];
size_t index, padLen;

/* Save number of bits */
Encode (bits, context->count, 8);

/* Pad out to 56 mod 64. */
index = (size_t)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);

/* Append length (before padding) */
MD5Update (context, bits, 8);

/* Store state in digest */
Encode (digest, context->state, 16);

/* Zeroize sensitive information. */
MD5_memset ((POINTER)context, 0, sizeof (*context));
}

/*
MD5 basic transformation. Transforms state based on block.
*/
void CSecurity::MD5Transform(
       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);

/* Round 1 */
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 */

/* Round 2 */
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 */

/* Round 3 */
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 */

/* Round 4 */
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;

/* Zeroize sensitive information. */
MD5_memset ((POINTER)x, 0, sizeof (x));
}

/*
Encodes input (UINT4) into output (unsigned char).
Assumes len is a multiple of 4.
*/
void CSecurity::Encode(
       unsigned char *output,
       UINT4 *input,
       size_t len
       )
{
size_t i, j;

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

/*
Decodes input (unsigned char) into output (UINT4).
Assumes len is a multiple of 4.
*/
void CSecurity::Decode(
       UINT4 *output,
       unsigned char *input,
       size_t len
       )
{
size_t i, j;

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

/*
Note: Replace "for loop" with standard memcpy if possible.
*/
void CSecurity::MD5_memcpy(
        POINTER output,
        POINTER input,
        size_t len
        )
{
size_t i;

for (i = 0; i < len; i++)
  output = input;
}

/*
Note: Replace "for loop" with standard memset if possible.
*/
void CSecurity::MD5_memset(
        POINTER output,
        int value,
        size_t len
        )
{
size_t i;

for (i = 0; i < len; i++)
  ((char *)output) = (char)value;
}

/*
Digests a string and prints the result.
*/
void CSecurity::MD5( const char *string ,char *lpMD5StringBuffer )
{
MD5_CTX context;
unsigned char digest[16];
/*char output1[33]; */
static char output[33]={""};
/*size_t*/size_t len = strlen (string);
int i;

MD5Init( &context);
MD5Update( &context, (unsigned char*)string, len );
MD5Final( digest, &context );

for (i = 0; i < 16; i++)
{
  sprintf(&(lpMD5StringBuffer[2*i]),"%02x",(unsigned char)digest);
  sprintf(&(lpMD5StringBuffer[2*i+1]),"%02x",(unsigned char)(digest<<4));
}
for(i=0;i<32;i++)
{
  output=lpMD5StringBuffer;
}
}

/*
get the string add one.
*/
void CSecurity::StringAddOne( char * orstring )
{
size_t len;
size_t i,n;

len = strlen(orstring);
n = len - 1;
for(i = n; i >= 0; i--)
{
  if(orstring=='9')
  {
   orstring = 'A';
   break;
  }
  else if(orstring=='Z')
  {
   orstring='a';
   break;
  }
  else if(orstring=='z')
  {
   orstring='0';
   continue;
  }
  else
   orstring += 1;
  break;
}
}
=============================stdafx.h=====================================
// stdafx.h : 标准系统包含文件的包含文件,
// 或是常用但不常更改的项目特定的包含文件
//

#pragma once

//导出
#define SECURITY_EXPORTS

#define WIN32_LEAN_AND_MEAN  // 从 Windows 头中排除极少使用的资料
// Windows 头文件:
#include <windows.h>

// TODO: 在此处引用程序要求的附加头文件
============================stdafx.cpp========================================

// stdafx.cpp : 只包括标准包含文件的源文件
// Security.pch 将成为预编译头
// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"

// TODO: 在 STDAFX.H 中
//引用任何所需的附加头文件,而不是在此文件中引用
=====================================================================

以上程序使用命令:@cl /GD /LD Security.cpp stdafx.cpp 编译即可



一些破解MD5的网站
http://www.cmd5.com
http://www.xmd5.com这两个网站都是国人做的
http://md5.mmkey.com
http://www.md5lookup.com/(对数字破解比较好)
http://md5.rednoize.com(对字母破解比较好)
http://nz.md5.crysm.net(从1到4位数字)- 好像关了
http://us.md5.crysm.net(美英字典的破解收集和IP地址)
http://www.xmd5.org(对数字破解比较好)
http://gdataonline.com(估计是基础字典的破解)
http://www.hashchecker.com(这个倒是说得很厉害,但是在实际中,很多次我在这里都找不到)
http://passcracking.ru
http://www.milw0rm.com/md5
http://plain-text.info(这个是我比较喜欢一个.也请你提交一些已破解的MD5)
http://www.securitystats.com/tools/hashcrack.php(多种破解.我试过...没有一次破解出来.非常没用)
http://www.schwett.com/md5/ - (破解挪威人(Norwegian)字典)
http://passcrack.spb.ru/
http://shm.pl/md5/
http://www.und0it.com/
http://www.neeao.com/md5/
http://md5.benramsey.com/
http://www.md5decrypt.com/
http://md5.khrone.pl/
http://www.csthis.com/md5/index.php
http://www.md5decrypter.com/
http://www.md5encryption.com/
http://www.md5database.net/
http://md5.xpzone.de/
http://md5.geeks.li/
http://www.hashreverse.com/
http://www.cmd5.com/english.aspx
http://www.md5.altervista.org/
http://md5.overclock.ch/biz/index.php?p=md5crack&;l=en
http://alimamed.pp.ru/md5/(如果你看不懂俄文,我告诉你,把你的MD5放到第2个格子)
http://md5crack.it-helpnet.de/index.php?op=add(德国的....)
http://cijfer.hua.fi/(Projects->md5 reverse lookup)
http://shm.hard-core.pl/md5/
http://www.thepanicroom.org/index.php?view=cracker
http://rainbowtables.net/services/results.php(我试过破过几次在这里)
http://rainbowcrack.com/(需要捐献)
http://www.securitydb.org/cracker/
http://passwordsecuritycenter.com/index.php?main_page=product_info&;cPath=3&products_id=7 这个是证明他们的破解商品的质量..好让你来买这个破解程序...但是...只要能破解到即可.你又不一定要买..
http://0ptix.co.nr/md5
lm:
http://sys9five.ath.cx:8080/hak5rtables/
http://lasecwww.epfl.ch/~oechslin/projects/ophcrack/
lm + ntlm:
http://plain-text.info
http://www.securitystats.com/tools/hashcrack.php
http://rainbowtables.net/services/results.php
http://rainbowcrack.com/
http://passwordsecuritycenter.com/index.php?main_page=product_info&;cPath=3&products_id=7

md4:
http://www.securitystats.com/tools/hashcrack.php
http://rainbowtables.net/services/results.php
http://rainbowcrack.com/
sha1:
http://www.securitystats.com/tools/hashcrack.php
http://passcrack.spb.ru/
http://www.hashreverse.com/
http://rainbowtables.net/services/results.php
http://rainbowcrack.com/
http://www.md5encryption.com/
http://passcracking.ru
target=_blank>http://www.shalookup.com/

开放分类:
信息加密加密算法摘要算法MD5
 
贡献者:
shdiaows198152bobbyzhushbfelfabe国学dgx_lsyd3岁月的音符
本词条在以下词条中被提及:
入侵检测王小云Tripwire散列函数

关于本词条的评论(共14条)查看更多评论>>

·很想认识下这为位收集资料的这位神。。。。。。。     460134979    11-05 01:49

·- -!! 厉害``     lp77301290    10-19 09:56

· 真是牛啊!就是学电子的我也是一头雾水啊!汗颜啊!     祝淼宇    10-15 14:50

对本词条发表评论:

最多不超过1000字


©2007 Baidu

转载于:https://www.cnblogs.com/BlueThinking/archive/2007/11/06/950647.html

什么叫MD5MD5通常做什么用处 这里是修真院后端小课堂,每篇分享文从 【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】 八个方面深度解析后端知识/技能,本篇分享的是: 【return的用法是什么?若在for循环中,还会执行下一次循环吗?】 【修真院java小课堂】什么叫MD5MD5通常做什么用处,为什么MD5不可逆,用做密码加密的时候仍然可能会被解密? 大家... 阅读详情

相关推荐

MD5流程以及安全性分析,MD5加盐,MD6,笔记

版权归其所有论文作者所有。并没写原始的地址,因为这是我整合的,作者太多,包括我。太匆忙,原作者可以联系我。简介MD5适用于数据完整性校验的。将任意长度的字节串(所以是基于底层的二进制串的),映射成为一个128位的大整数2^128种可能性。同样的内容经过md5,会得到同样的128位码。本质上是散列算法,有损的信息压缩,并且是不可逆的。MD5广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以M...

乱七八糟的笔记 2949

MD5】什么是MD5md5的简要描述

MD5:英文全称是 Message-Digest Algorithm 5。中文名为 消息摘要算法第五版。它是消息摘要算法,属于 Hash 算法的一种。正常情况下,它的结果是一个 长度为32位的16进制的字符串。也有一些地方会用到 16 位的 MD5的结果,它实际上是从 32位 字符串中取中间的第9位到第24位的部分,即长度是 16位。

No8g攻城狮的博客 1万+

【时时三省】tessy 进入调试模式 教程

山不在高,有仙则名。水不在深,有龙则灵。----CSDN 时时三省。

时时三省的博客 730

MD5算法全解析

前言 这段时间刚好正在做软件安全的实验和课设,学习了各种加密算法,比如对称加密算法的DES,AES;非对称加密算法的RSA,再如今天要讲的主角-单向加密算法的MD5。为什么这么多算法,MD5成为了今天的猪脚呢?,这是因为个人感觉在目前Android开发中MD5算是比较常用的,所以很值得一讲。所以今天让我带你们来全面认识我们的主角MD5。 一、基本概念 1. 单向加密算法 在介绍MD5算法前,很有必...

jsyjst的博客 9907

基于QT的MD5加密实例

MD5在QT4中已有实现: MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准...

yangzijiangtou 1415

MD5算法实现原理

目录1 MD5 简介2 MD5 实现步骤2.1 将明文变为 ASCII 码2.2 填充和附加2.3 分组2.4 预处理2.5 循环加工3 blueimp-md5 源码4 遗留的问题4.1 四个非线性函数4.2 左循环偏移量4.3 正弦补充值5 总结 1 MD5 简介 信息摘要算法 MD5 (Message Digest 5),其中数字 5 代表这是第五代算法,之前还有 MD1、MD2、MD3 和 ...

syzdev的博客 4305

MD5算法详解

md5算法

123 5万+

MD5加密算法简介 ()

MD5加密算法简介 ()[@more@]MD5加密算法简介 一、算法实现(载自绿色兵团) 1、MD5算法是对输入的数据进行补位,使得如果数据位长度LEN对512求余的结果 是448。 即数据扩展至K*512+448位。...

csd3176的博客 132

md5用途简介

1. 什么是md5? md5计算,是对原始消息做有损的压缩算法,无论消息(输入值)的长度是多少字节,都会生成一个固定长度(128位/16字节)的消息摘要(输出值) md5有以下特性: 不可逆(不能从消息摘要恢复出原始输入) 恒定性(同样的输入,经过md5算法经过同样的迭代次数,产生的输出一定是相同的) 不可预测(输入内容做轻微改变,输出大相径庭) 等等 2. md5有什么作用 数据完整性校验 文件完整性校验 文件经过网络传输、拷贝或其他操作后,可以通过文件的md5值判断文件内容是否发生了改变。文

lgfun的专栏 5606

C++|MD5简介

将结构体的成员变量换为字节流。使用MD5算法对字节流进行哈希计算。将计算出的哈希值换为可读的格式(如十六进制字符串)。以下是一个简单的示例,演示如何对一个自定义结构体进行MD5哈希:首先,你需要一个MD5库。在C++中,你可以使用开源库如openssl来实现MD5。以下是使用openssl// 假设这是你的自定义结构体int a;float b;// 将结构体换为字节流的函数// 以网络字节顺序(大端)写入数据const。

编程改变世界。想做一些改变世界的产品。感谢一键三连。 2793

JavaScript JS 图片MD5 ImgMD5 文件MD5 URL文件MD5 获取原始文件的MD5

首先引入JS文件: <script src="https://cdn.bootcss.com/spark-md5/3.0.0/spark-md5.min.js"></script> 测试代码: <script> !function () { var xhr = new XMLHttpRequest(); // ...

星光的博客 3203

MD5简介

1. md5简介 md5的全称是md5信息摘要算法(英文:MD5 Message-Digest Algorithm ),一种被广泛使用的密码散列函数,可以产生一个128位(16字节,1字节8位)的散列值(常见的是用32位的16进制表示,比如:0caa3b23b8da53f9e4e041d95dc8fa2c),用于确保信息传输的完整一致。 2. md5原理 md5将整个文件当做一个大文本信息,通过不可逆的字符串变换算法,产生一个唯一的MD5信息摘要。文件的md5类似于人的指纹,在世界上是独立无二的,如果

weixin_65795413的博客 1万+

MD5简介

一、概述 MD5(Message-Digest Algorithm 5),即消息摘要算法第五版,是一种被广泛使用的密码散列函数。散列算法的基础原理是:将数据(如一段文字)运算,变为另一段固定长度的值。 MD5 可以产生出一个128位(16字节)的散列值(hash value),用于确保传输的信息完整一致。 MD5 由美国密码学家 Ronald Linn Rivest 设计,于1992年公开,用以取代 MD4 算法。MD5 算法的程序在 RFC 1321 中被加以规范。 二、原理 MD5将整个文件当做一个大文

qq_44796643的博客 2860

C# md5加密,MD516位

字符串MD5加密 public static string MD5Encrypt(string EncryptString) { if (string.IsNullOrEmpty(EncryptString)) { throw (new Exception("密文不得为空")); } var clearBytes = Encoding.UTF8.Ge...

the_heart_is_die的博客 2771

MD5算法简介

MD5简单介绍及其介绍

bdn_nbd的博客 962

java大写md5_JAVA MD5加密大写

可以直接复制使用/****/package com.trafree.banking.server.hardcore.util;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;/*** @author...

weixin_33188832的博客 2192

md5 简介

MD5简介MD5的全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经MD2、MD3和MD4发展而来。 Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了“字节串”而不是“字符串”这个词,是因为这种变

zuiyuezhou888的专栏 926

MD5加密解密简介和应用

MD5原理和应用 一:什么是md5 MD5信息摘要算法(MD5 Message-Digest Algorithm),一种 被广泛使用的密码散列函数,可以产生一个128位(16字节)的散列值,用于确保信息传输的一致。MD5 是一种不可逆的加密算法。MD5是一种常用的加密解密的算法,但是在1996年被证明该算法 存在弱点,在2004年证实该算法无法防止碰撞(概论很低),因此不适用于 安全认证。在一些安全系数不需要很高的应用中还是可以应用的。 二:MD5在前端项目中的应用 1)加密 最近在写一个react应用,其

weixin_53011724的博客 5251

自适应控制 (Adaptive Control) 算法详解及案例分析

自适应控制是一种能够在线调整控制器参数以适应系统动态变化的控制方法。其核心思想是通过实时估计系统参数或调整控制器参数,使系统在不确定性或动态变化的环境中仍能保持稳定性和性能。

闲人编程的博客 4008

爱普生L3250清零教程软件+图解

爱普生L3250是一款多功能一体机,集打印、扫描和复印功能于一身,深受家庭和小型办公室用户喜爱。然而,随着时间的推移,打印机可能会遇到墨盒计数器满的问题,导致无法正常工作。这时,就需要使用清零软件来重置打印机的计数器,以便继续使用。本文将详细介绍爱普生L3250清零软件的用途、工作原理以及如何操作。清零软件是针对打印机墨盒计数器设计的工具。在爱普生的墨水系统中,每个墨盒都有一个内置的计数器,用于追踪墨水的消耗。当计数器达到预设值时,即使墨盒还有剩余,打印机也会显示墨盒已空,从而影响正常打印。爱普生L3250清零软件就是为了解决这个问题,它可以重置计数器,让打印机恢复工作。该软件的下载是免费且无需注册或绑定,这为用户提供了极大的便利。不过,需要注意的是,由于该软件未经官方测试,使用前建议先备份重要数据,以防可能存在的风险。使用清零软件的过程大致如下:1. **下载与安装**:从提供的压缩包中提取出爱普生L3250清零软件,然后按照安装向导进行安装。确保计算机的操作系统与软件兼容。2. **连接打印机**:通过USB线将打印机连接到电脑,确保打印机已开启并处于就绪状态。

上一篇: VB常用函数
下一篇: 如何生成静态页
weixin_30824277
博客等级 码龄11年 118粉丝 0原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值