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小時內結束”。

用的是哈希函數,在計算機網絡中應用較多的不可逆加密算法有RSA公司發明的MD5算法和由美國國家技術標準研究所建議的安全散列算法SHA.
算法的應用

  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值在這個字典中檢索。我們假設密碼的最大長度爲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
http://www.shalookup.com/
 
發佈了66 篇原創文章 · 獲贊 10 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章