MD5簡介:

http://www.cmd5.com/password.aspx 在線破解

MD5的全稱是Message-Digest Algorithm 5,在90年代初由MIT的電腦科學實驗室和RSA Data Security Inc發明,經MD2、MD3和MD4發展而來。

Message-Digest泛指位元組串(Message)的Hash變換,就是把一個任意長度的位元組串變換成一定長的大整數。請注意我使用了“位元組串”而不是“字串”這個詞,是因為這種變換只與位元組的值有關,與字元集或編碼方式無關。

MD5將任意長度的“位元組串”變換成一個128bit的大整數,並且它是一個不可逆的字串變換演算法,換句話說就是,即使你看到根源程式和演算法描述,也無法將一個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※※※※※※※※※※※※※※※※※※※※※※※※
#i nclude "global.h"
#i nclude "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;

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

static void MD5_memset (output, value, len)
POINTER output;
int value;
unsigned int len;
{
unsigned int i;

for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
}
————————————————C代碼結束——————————


在VB中實現MD5演算法
——————————————————————————————————————————
Option Explicit

Dim w1 As String, w2 As String, w3 As String, w4 As String

Function MD5F(ByVal tempstr As String, ByVal w As String, ByVal X As String, ByVal y As String, ByVal z As String, ByVal Xin As String, ByVal qdata As String, ByVal rots As Integer)
MD5F = BigMod32Add(RotLeft(BigMod32Add(BigMod32Add(w, tempstr), BigMod32Add(Xin, qdata)), rots), X)
End Function

Sub MD5F1(w As String, ByVal X As String, ByVal y As String, ByVal z As String, ByVal Xin As String, ByVal qdata As String, ByVal rots As Integer)
Dim tempstr As String

tempstr = BigXOR(z, BigAND(X, BigXOR(y, z)))
w = MD5F(tempstr, w, X, y, z, Xin, qdata, rots)
End Sub

Sub MD5F2(w As String, ByVal X As String, ByVal y As String, ByVal z As String, ByVal Xin As String, ByVal qdata As String, ByVal rots As Integer)
Dim tempstr As String

tempstr = BigXOR(y, BigAND(z, BigXOR(X, y)))
w = MD5F(tempstr, w, X, y, z, Xin, qdata, rots)
End Sub

Sub MD5F3(w As String, ByVal X As String, ByVal y As String, ByVal z As String, ByVal Xin As String, ByVal qdata As String, ByVal rots As Integer)
Dim tempstr As String

tempstr = BigXOR(X, BigXOR(y, z))
w = MD5F(tempstr, w, X, y, z, Xin, qdata, rots)
End Sub

Sub MD5F4(w As String, ByVal X As String, ByVal y As String, ByVal z As String, ByVal Xin As String, ByVal qdata As String, ByVal rots As Integer)
Dim tempstr As String

tempstr = BigXOR(y, BigOR(X, BigNOT(z)))
w = MD5F(tempstr, w, X, y, z, Xin, qdata, rots)
End Sub

Function MD5_Calc(ByVal hashthis As String) As String
ReDim buf(0 To 3) As String
ReDim Xin(0 To 15) As String
Dim tempnum As Integer, tempnum2 As Integer, loopit As Integer, loopouter As Integer, loopinner As Integer
Dim a As String, b As String, c As String, d As String

tempnum = 8 * Len(hashthis)
hashthis = hashthis + Chr$(128) 'Add binary 10000000
tempnum2 = 56 - Len(hashthis) Mod 64

If tempnum2 < 0 Then
tempnum2 = 64 + tempnum2
End If

hashthis = hashthis + String$(tempnum2, Chr$(0))

For loopit = 1 To 8
hashthis = hashthis + Chr$(tempnum Mod 256)
tempnum = tempnum - tempnum Mod 256
tempnum = tempnum / 256
Next loopit


buf(0) = "67452301"
buf(1) = "efcdab89"
buf(2) = "98badcfe"
buf(3) = "10325476"


For loopouter = 0 To Len(hashthis) / 64 - 1
a = buf(0)
b = buf(1)
c = buf(2)
d = buf(3)

' Get the 512 bits
For loopit = 0 To 15
Xin(loopit) = ""
For loopinner = 1 To 4
Xin(loopit) = Hex$(Asc(Mid$(hashthis, 64 * loopouter + 4 * loopit + loopinner, 1))) + Xin(loopit)
If Len(Xin(loopit)) Mod 2 Then Xin(loopit) = "0" + Xin(loopit)
Next loopinner
Next loopit


' 第一輪迴圈
MD5F1 a, b, c, d, Xin(0), "d76aa478", 7
MD5F1 d, a, b, c, Xin(1), "e8c7b756", 12
MD5F1 c, d, a, b, Xin(2), "242070db", 17
MD5F1 b, c, d, a, Xin(3), "c1bdceee", 22
MD5F1 a, b, c, d, Xin(4), "f57c0faf", 7
MD5F1 d, a, b, c, Xin(5), "4787c62a", 12
MD5F1 c, d, a, b, Xin(6), "a8304613", 17
MD5F1 b, c, d, a, Xin(7), "fd469501", 22
MD5F1 a, b, c, d, Xin(8), "698098d8", 7
MD5F1 d, a, b, c, Xin(9), "8b44f7af", 12
MD5F1 c, d, a, b, Xin(10), "ffff5bb1", 17
MD5F1 b, c, d, a, Xin(11), "895cd7be", 22
MD5F1 a, b, c, d, Xin(12), "6b901122", 7
MD5F1 d, a, b, c, Xin(13), "fd987193", 12
MD5F1 c, d, a, b, Xin(14), "a679438e", 17
MD5F1 b, c, d, a, Xin(15), "49b40821", 22

' 第二輪迴圈
MD5F2 a, b, c, d, Xin(1), "f61e2562", 5
MD5F2 d, a, b, c, Xin(6), "c040b340", 9
MD5F2 c, d, a, b, Xin(11), "265e5a51", 14
MD5F2 b, c, d, a, Xin(0), "e9b6c7aa", 20
MD5F2 a, b, c, d, Xin(5), "d62f105d", 5
MD5F2 d, a, b, c, Xin(10), "02441453", 9
MD5F2 c, d, a, b, Xin(15), "d8a1e681", 14
MD5F2 b, c, d, a, Xin(4), "e7d3fbc8", 20
MD5F2 a, b, c, d, Xin(9), "21e1cde6", 5
MD5F2 d, a, b, c, Xin(14), "c33707d6", 9
MD5F2 c, d, a, b, Xin(3), "f4d50d87", 14
MD5F2 b, c, d, a, Xin(8), "455a14ed", 20
MD5F2 a, b, c, d, Xin(13), "a9e3e905", 5
MD5F2 d, a, b, c, Xin(2), "fcefa3f8", 9
MD5F2 c, d, a, b, Xin(7), "676f02d9", 14
MD5F2 b, c, d, a, Xin(12), "8d2a4c8a", 20

' 第三輪迴圈
MD5F3 a, b, c, d, Xin(5), "fffa3942", 4
MD5F3 d, a, b, c, Xin(8), "8771f681", 11
MD5F3 c, d, a, b, Xin(11), "6d9d6122", 16
MD5F3 b, c, d, a, Xin(14), "fde5380c", 23
MD5F3 a, b, c, d, Xin(1), "a4beea44", 4
MD5F3 d, a, b, c, Xin(4), "4bdecfa9", 11
MD5F3 c, d, a, b, Xin(7), "f6bb4b60", 16
MD5F3 b, c, d, a, Xin(10), "bebfbc70", 23
MD5F3 a, b, c, d, Xin(13), "289b7ec6", 4
MD5F3 d, a, b, c, Xin(0), "e27fa", 11
MD5F3 c, d, a, b, Xin(3), "d4ef3085", 16
MD5F3 b, c, d, a, Xin(6), "04881d05", 23
MD5F3 a, b, c, d, Xin(9), "d9d4d039", 4
MD5F3 d, a, b, c, Xin(12), "e6db99e5", 11
MD5F3 c, d, a, b, Xin(15), "1fa27cf8", 16
MD5F3 b, c, d, a, Xin(2), "c4ac5665", 23

' 第四輪迴圈
MD5F4 a, b, c, d, Xin(0), "f4292244", 6
MD5F4 d, a, b, c, Xin(7), "432aff97", 10
MD5F4 c, d, a, b, Xin(14), "ab9423a7", 15
MD5F4 b, c, d, a, Xin(5), "fc93a039", 21
MD5F4 a, b, c, d, Xin(12), "655b59c3", 6
MD5F4 d, a, b, c, Xin(3), "8f0ccc92", 10
MD5F4 c, d, a, b, Xin(10), "ffeff47d", 15
MD5F4 b, c, d, a, Xin(1), "85845dd1", 21
MD5F4 a, b, c, d, Xin(8), "6fa87e4f", 6
MD5F4 d, a, b, c, Xin(15), "fe2ce6e0", 10
MD5F4 c, d, a, b, Xin(6), "a3014314", 15
MD5F4 b, c, d, a, Xin(13), "4e0811a1", 21
MD5F4 a, b, c, d, Xin(4), "f7537e82", 6
MD5F4 d, a, b, c, Xin(11), "bd3af235", 10
MD5F4 c, d, a, b, Xin(2), "2ad7d2bb", 15
MD5F4 b, c, d, a, Xin(9), "eb86d391", 21

buf(0) = BigAdd(buf(0), a)
buf(1) = BigAdd(buf(1), b)
buf(2) = BigAdd(buf(2), c)
buf(3) = BigAdd(buf(3), d)
Next loopouter

hashthis = ""
For loopit = 0 To 3
For loopinner = 3 To 0 Step -1
hashthis = hashthis + Chr(Val("&H" + Mid$(buf(loopit), 1 + 2 * loopinner, 2)))
Next loopinner
Next loopit

MD5_Calc = hashthis
End Function

Function BigMod32Add(ByVal value1 As String, ByVal value2 As String) As String
BigMod32Add = Right$(BigAdd(value1, value2), 8)
End Function

Public Function BigAdd(ByVal value1 As String, ByVal value2 As String) As String
Dim valueans As String
Dim loopit As Integer, tempnum As Integer

tempnum = Len(value1) - Len(value2)
If tempnum < 0 Then
value1 = Space$(Abs(tempnum)) + value1
ElseIf tempnum > 0 Then
value2 = Space$(Abs(tempnum)) + value2
End If

tempnum = 0
For loopit = Len(value1) To 1 Step -1
tempnum = tempnum + Val("&H" + Mid$(value1, loopit, 1)) + Val("&H" + Mid$(value2, loopit, 1))
valueans = Hex$(tempnum Mod 16) + valueans
tempnum = Int(tempnum / 16)
Next loopit

If tempnum <> 0 Then
valueans = Hex$(tempnum) + valueans
End If

BigAdd = Right(valueans, 8)
End Function

Public Function RotLeft(ByVal value1 As String, ByVal rots As Integer) As String
Dim tempstr As String
Dim loopit As Integer, loopinner As Integer
Dim tempnum As Integer

rots = rots Mod 32

If rots = 0 Then
RotLeft = value1
Exit Function
End If

value1 = Right$(value1, 8)
tempstr = String$(8 - Len(value1), "0") + value1
value1 = ""

' 轉換成二進位形式
For loopit = 1 To 8
tempnum = Val("&H" + Mid$(tempstr, loopit, 1))
For loopinner = 3 To 0 Step -1
If tempnum And 2 ^ loopinner Then
value1 = value1 + "1"
Else
value1 = value1 + "0"
End If
Next loopinner
Next loopit
tempstr = Mid$(value1, rots + 1) + Left$(value1, rots)

' 轉換為十六進位
value1 = ""
For loopit = 0 To 7
tempnum = 0
For loopinner = 0 To 3
If Val(Mid$(tempstr, 4 * loopit + loopinner + 1, 1)) Then

tempnum = tempnum + 2 ^ (3 - loopinner)
End If
Next loopinner
value1 = value1 + Hex$(tempnum)
Next loopit

RotLeft = Right(value1, 8)
End Function

Function BigAND(ByVal value1 As String, ByVal value2 As String) As String
Dim valueans As String
Dim loopit As Integer, tempnum As Integer

tempnum = Len(value1) - Len(value2)
If tempnum < 0 Then
value2 = Mid$(value2, Abs(tempnum) + 1)
ElseIf tempnum > 0 Then
value1 = Mid$(value1, tempnum + 1)
End If

For loopit = 1 To Len(value1)
valueans = valueans + Hex$(Val("&H" + Mid$(value1, loopit, 1)) And Val("&H" + Mid$(value2, loopit, 1)))
Next loopit

BigAND = valueans
End Function

Function BigNOT(ByVal value1 As String) As String
Dim valueans As String
Dim loopit As Integer

value1 = Right$(value1, 8)
value1 = String$(8 - Len(value1), "0") + value1
For loopit = 1 To 8
valueans = valueans + Hex$(15 Xor Val("&H" + Mid$(value1, loopit, 1)))
Next loopit

BigNOT = valueans
End Function

Function BigOR(ByVal value1 As String, ByVal value2 As String) As String
Dim valueans As String
Dim loopit As Integer, tempnum As Integer

tempnum = Len(value1) - Len(value2)
If tempnum < 0 Then
valueans = Left$(value2, Abs(tempnum))
value2 = Mid$(value2, Abs(tempnum) + 1)
ElseIf tempnum > 0 Then
valueans = Left$(value1, Abs(tempnum))
value1 = Mid$(value1, tempnum + 1)
End If

For loopit = 1 To Len(value1)
valueans = valueans + Hex$(Val("&H" + Mid$(value1, loopit, 1)) Or Val("&H" + Mid$(value2, loopit, 1)))
Next loopit

BigOR = valueans
End Function

Function BigXOR(ByVal value1 As String, ByVal value2 As String) As String
Dim valueans As String
Dim loopit As Integer, tempnum As Integer

tempnum = Len(value1) - Len(value2)
If tempnum < 0 Then
valueans = Left$(value2, Abs(tempnum))
value2 = Mid$(value2, Abs(tempnum) + 1)
ElseIf tempnum > 0 Then
valueans = Left$(value1, Abs(tempnum))
value1 = Mid$(value1, tempnum + 1)
End If

For loopit = 1 To Len(value1)
valueans = valueans + Hex$(Val("&H" + Mid$(value1, loopit, 1)) Xor Val("&H" + Mid$(value2, loopit, 1)))
Next loopit

BigXOR = Right(valueans, 8)
End Function
來源連接!
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怎麼都應該算得上是非常安全的了。
   演算法的應用
   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是逐位元奇偶操作符。
   假設Mj表示消息的第j個子分組(從0到15),<<
    FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti)<<    GG(a,b,c,d,Mj,s,ti)表示a=b+((a+(G(b,c,d)+Mj+ti)<<    HH(a,b,c,d,Mj,s,ti)表示a=b+((a+(H(b,c,d)+Mj+ti)<<    II(a,b,c,d,Mj,s,ti)表示a=b+((a+(I(b,c,d)+Mj+ti)<<
   這四輪(64步)是:
   第一輪
    FF(a,b,c,d,M0,7,0xd76aa478)
    FF(d,a,b,c,M1,12,0xe8c7b756)
    FF(c,d,a,b,M2,17,0x242070db)
FF(b,c,d,a,M3,22,0xc1bdceee)
    FF(a,b,c,d,M4,7,0xf57c0faf)
    FF(d,a,b,c,M5,12,0x4787c62a)
    FF(c,d,a,b,M6,17,0xa8304613)
    FF(b,c,d,a,M7,22,0xfd469501)
    FF(a,b,c,d,M8,7,0x698098d8)
    FF(d,a,b,c,M9,12,0x8b44f7af)
    FF(c,d,a,b,M10,17,0xffff5bb1)
    FF(b,c,d,a,M11,22,0x895cd7be)
    FF(a,b,c,d,M12,7,0x6b901122)
    FF(d,a,b,c,M13,12,0xfd987193)
    FF(c,d,a,b,M14,17,0xa679438e)
    FF(b,c,d,a,M15,22,0x49b40821)
   第二輪
    GG(a,b,c,d,M1,5,0xf61e2562)
    GG(d,a,b,c,M6,9,0xc040b340)
    GG(c,d,a,b,M11,14,0x265e5a51)
    GG(b,c,d,a,M0,20,0xe9b6c7aa)
    GG(a,b,c,d,M5,5,0xd62f105d)
    GG(d,a,b,c,M10,9,0x02441453)
    GG(c,d,a,b,M15,14,0xd8a1e681)
    GG(b,c,d,a,M4,20,0xe7d3fbc8)
    GG(a,b,c,d,M9,5,0x21e1cde6)
    GG(d,a,b,c,M14,9,0xc33707d6)
    GG(c,d,a,b,M3,14,0xf4d50d87)
    GG(b,c,d,a,M8,20,0x455a14ed)
    GG(a,b,c,d,M13,5,0xa9e3e905)
    GG(d,a,b,c,M2,9,0xfcefa3f8)
    GG(c,d,a,b,M7,14,0x676f02d9)
    GG(b,c,d,a,M12,20,0x8d2a4c8a)
   第三輪
    HH(a,b,c,d,M5,4,0xfffa3942)
    HH(d,a,b,c,M8,11,0x8771f681)
    HH(c,d,a,b,M11,16,0x6d9d6122)
    HH(b,c,d,a,M14,23,0xfde5380c)
    HH(a,b,c,d,M1,4,0xa4beea44)
    HH(d,a,b,c,M4,11,0x4bdecfa9)
    HH(c,d,a,b,M7,16,0xf6bb4b60)
    HH(b,c,d,a,M10,23,0xbebfbc70)
    HH(a,b,c,d,M13,4,0x289b7ec6)
    HH(d,a,b,c,M0,11,0xeaa127fa)
    HH(c,d,a,b,M3,16,0xd4ef3085)
    HH(b,c,d,a,M6,23,0x04881d05)
    HH(a,b,c,d,M9,4,0xd9d4d039)
    HH(d,a,b,c,M12,11,0xe6db99e5)
    HH(c,d,a,b,M15,16,0x1fa27cf8)
    HH(b,c,d,a,M2,23,0xc4ac5665)
   第四輪
    II(a,b,c,d,M0,6,0xf4292244)
    II(d,a,b,c,M7,10,0x432aff97)
    II(c,d,a,b,M14,15,0xab9423a7)
    II(b,c,d,a,M5,21,0xfc93a039)
    II(a,b,c,d,M12,6,0x655b59c3)
    II(d,a,b,c,M3,10,0x8f0ccc92)
    II(c,d,a,b,M10,15,0xffeff47d)
    II(b,c,d,a,M1,21,0x85845dd1)
    II(a,b,c,d,M8,6,0x6fa87e4f)
    II(d,a,b,c,M15,10,0xfe2ce6e0)
    II(c,d,a,b,M6,15,0xa3014314)
    II(b,c,d,a,M13,21,0x4e0811a1)
    II(a,b,c,d,M4,6,0xf7537e82)
    II(d,a,b,c,M11,10,0xbd3af235)
    II(c,d,a,b,M2,15,0x2ad7d2bb)
    II(b,c,d,a,M9,21,0xeb86d391)
   常數ti可以如下選擇:
   在第i步中,ti是4294967296*abs(sin(i))的整數部分,i的單位是弧度。(4294967296等於2的32次方)
所有這些完成之後,將A、B、C、D分別加上a、b、c、d。然後用下一分組資料繼續運行演算法,最後的輸出是A、B、C和D的級聯。
   當你按照我上面所說的方法實現MD5演算法以後,你可以用以下幾個資訊對你做出來的程式作一個簡單的測試,看看程式有沒有錯誤。
    MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
    MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
    MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
    MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
    MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
    MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
d174ab98d277d9f5a5611c2c9f419d9f
    MD5 ("123456789012345678901234567890123456789012345678901234567890123456789
01234567890") = 57edf4a22be3c955ac49da2e2107b67a
   如果你用上面的資訊分別對你做的MD5演算法實例做測試,最後得出的結論和標準答案完全一樣,那我就要在這裏象你道一聲祝賀了。要知道,我的程式在第一次編譯成功的時候是沒有得出和上面相同的結果的。

   MD5的安全性
   MD5相對MD4所作的改進:
    1. 增加了第四輪;
    2. 每一步均有唯一的加法常數;
    3. 為減弱第二輪中函數G的對稱性從(X&Y)|(X&Z)|(Y&Z)變為(X&Z)|(Y&(~Z));
    4. 第一步加上了上一步的結果,這將引起更快的雪崩效應;
    5. 改變了第二輪和第三輪中訪問消息子分組的次序,使其更不相似;
    6. 近似優化了每一輪中的迴圈左移位移量以實現更快的雪崩效應。各輪的位移量互不相同。

By tony

自由軟體愛好者~喜歡不斷的思考各種問題,有新的事物都會想去學習嘗試 做實驗並熱衷研究 沒有所謂頂天的技術 只有謙虛及不斷的學習 精進專業,本站主要以分享系統及網路相關知識、資源而建立。 Github http://stnet253.github.io

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料