MD5的介绍,算法以及实现

MD5简介:

MD5是英文“Message-Digest Algorithm Five”的简写,在90年代初由MIT的计算机科学实验室和 RSA Data Security Inc发明,经历了最初的MD2、MD3和MD4的发展演化而来。“Message-Digest”泛指字节串 (Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了“字节串”而不是“字符串”这个词,是因为这种变换 只与字节的值有关,与字符集或编码方式无关,也就是很多朋友问MD5可以机密中文字符的原理。

MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是:既便是MD5算法的源代码满天飞,使 得任何人都可以了解MD5的详尽算法描述,但是却也绝对没有任何人可以将一个经由MD5算法加密过的字符串变换回原始的字符串,从数学原理上说,是因为原 始的字符串有无穷多个,这有点象不存在反函数的数学函数。

MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readme.txt文件中,并对这个readme.txt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内 容,你对这个文件重新计算MD5时就会发现两者的不同,以便提早发现文件已经被改动过了。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的 “抵赖”,这就是所谓的数字签名应用。

MD5还可以被广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的, 用户在进行登陆验证的时候,系 统是把用户输入的密码计算成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进行加密转换,然后再用第二个算法的 逆算法进行演变,得出原始的用户名。具体来说:我们设用户名为StrName,注册码为StrRegNO,那么如果哪一位共享软件的作者采用如下算法作为 他自己软件的注册算法:‘If MD5(StrName)=MD5(strRegNO)  then "register successful"  Else "register unsuccessful " ’那么对于Cracker来 说只要可以看出软件采用了MD5算法就可以写出注册机了,但是如果作者采用如下算法:‘If MD5(StrRegNO)=MD5(StrName)  Then "register successful"  Else "register unsuccessful " ’的话,那么我想连共享软件 作者自己也必须通过穷举法才可以求出注册用户的序列号了。所以对于破解者来说只要可以看出软件的注册算法采用的是MD5就足够了。

MD5代码的特点也非常的明显,跟踪时很容易发现。如果软件采用MD5算法,在数据初始化的时候必然会用到以下四个常数:
A = 0x01234567
B = 0x89abcdef
C = 0xfedcba98
D = 0x76543210
若常数不等,则可能是变形的MD5算法或者根本就不是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,Delphi和VB中实现MD5算法
C语言举例:
--------------------------------------------

*/
#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;

  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算法
------------------------------------------
模块源码如下: 

Private Const OFFSET_4 = 4294967296# 
Private Const MAXINT_4 = 2147483647 
Private State(4) As Long 
Private ByteCounter As Long 
Private ByteBuffer(63) As Byte 
Private Const S11 = 7 
Private Const S12 = 12 
Private Const S13 = 17 
Private Const S14 = 22 
Private Const S21 = 5 
Private Const S22 = 9 
Private Const S23 = 14 
Private Const S24 = 20 
Private Const S31 = 4 
Private Const S32 = 11 
Private Const S33 = 16 
Private Const S34 = 23 
Private Const S41 = 6 
Private Const S42 = 10 
Private Const S43 = 15 
Private Const S44 = 21 
Property Get RegisterA() As String 
    RegisterA = State(1) 
End Property 
Property Get RegisterB() As String 
    RegisterB = State(2) 
End Property 

Property Get RegisterC() As String 
    RegisterC = State(3) 
End Property 

Property Get RegisterD() As String 
    RegisterD = State(4) 
End Property 
Public Function Md5_String_Calc(SourceString As String) As String 
    MD5Init 
    MD5Update LenB(StrConv(SourceString, vbFromUnicode)), StringToArray(SourceString) 
    MD5Final 
    Md5_String_Calc = GetValues 
End Function 
Public Function Md5_File_Calc(InFile As String) As String 
On Error GoTo errorhandler 
GoSub begin 

errorhandler 
    DigestFileToHexStr = "" 
    Exit Function 
    
begin: 
    Dim FileO As Integer 
    FileO = FreeFile 
    Call FileLen(InFile) 
    Open InFile For Binary Access Read As #FileO 
    MD5Init 
    Do While Not EOF(FileO) 
        Get #FileO, , ByteBuffer 
        If Loc(FileO) < LOF(FileO) Then 
            ByteCounter = ByteCounter + 64 
            MD5Transform ByteBuffer 
        End If 
    Loop 
    ByteCounter = ByteCounter + (LOF(FileO) Mod 64) 
    Close #FileO 
    MD5Final 
    Md5_File_Calc = GetValues 
End Function 
Private Function StringToArray(InString As String) As Byte() 
    Dim I As Integer, bytBuffer() As Byte 
    ReDim bytBuffer(LenB(StrConv(InString, vbFromUnicode))) 
    bytBuffer = StrConv(InString, vbFromUnicode) 
    StringToArray = bytBuffer 
End Function 
Public Function GetValues() As String 
    GetValues = LongToString(State(1)) & LongToString(State(2)) & LongToString(State(3)) & LongToString(State(4)) 
End Function 
Private Function LongToString(Num As Long) As String 
        Dim A As Byte, B As Byte, C As Byte, D As Byte 
        A = Num And &HFF& 
        If A < 16 Then LongToString = "0" & Hex(A) Else LongToString = Hex(A) 
        B = (Num And &HFF00&) / 256 
        If B < 16 Then LongToString = LongToString & "0" & Hex(B) Else LongToString = LongToString & Hex(B) 
        C = (Num And &HFF0000) / 65536 
        If C < 16 Then LongToString = LongToString & "0" & Hex(C) Else LongToString = LongToString & Hex(C) 
        If Num < 0 Then D = ((Num And &H7F000000) / 16777216) Or &H80& Else D = (Num And &HFF000000) / 16777216 
        If D < 16 Then LongToString = LongToString & "0" & Hex(D) Else LongToString = LongToString & Hex(D) 
End Function 

Public Sub MD5Init() 
    ByteCounter = 0 
    State(1) = UnsignedToLong(1732584193#) 
    State(2) = UnsignedToLong(4023233417#) 
    State(3) = UnsignedToLong(2562383102#) 
    State(4) = UnsignedToLong(271733878#) 
End Sub 

Public Sub MD5Final() 
    Dim dblBits As Double, padding(72) As Byte, lngBytesBuffered As Long 
    padding(0) = &H80 
    dblBits = ByteCounter * 8 
    lngBytesBuffered = ByteCounter Mod 64 
    If lngBytesBuffered <= 56 Then MD5Update 56 - lngBytesBuffered, padding Else MD5Update 120 - ByteCounter, padding 
    padding(0) = UnsignedToLong(dblBits) And &HFF& 
    padding(1) = UnsignedToLong(dblBits) / 256 And &HFF& 
    padding(2) = UnsignedToLong(dblBits) / 65536 And &HFF& 
    padding(3) = UnsignedToLong(dblBits) / 16777216 And &HFF& 
    padding(4) = 0 
    padding(5) = 0 
    padding(6) = 0 
    padding(7) = 0 
    MD5Update 8, padding 
End Sub 
Public Sub MD5Update(InputLen As Long, InputBuffer() As Byte) 
    Dim II As Integer, I As Integer, J As Integer, K As Integer, lngBufferedBytes As Long, lngBufferRemaining As Long, lngRem As Long 

    lngBufferedBytes = ByteCounter Mod 64 
    lngBufferRemaining = 64 - lngBufferedBytes 
    ByteCounter = ByteCounter + InputLen 

    If InputLen >= lngBufferRemaining Then 
        For II = 0 To lngBufferRemaining - 1 
            ByteBuffer(lngBufferedBytes + II) = InputBuffer(II) 
        Next II 
        MD5Transform ByteBuffer 
        lngRem = (InputLen) Mod 64 
        For I = lngBufferRemaining To InputLen - II - lngRem Step 64 
            For J = 0 To 63 
                ByteBuffer(J) = InputBuffer(I + J) 
            Next J 
            MD5Transform ByteBuffer 
        Next I 
        lngBufferedBytes = 0 
    Else 
      I = 0 
    End If 
    For K = 0 To InputLen - I - 1 
        ByteBuffer(lngBufferedBytes + K) = InputBuffer(I + K) 
    Next K 
End Sub 
Private Sub MD5Transform(Buffer() As Byte) 
    Dim X(16) As Long, A As Long, B As Long, C As Long, D As Long 
    
    A = State(1) 
    B = State(2) 
    C = State(3) 
    D = State(4) 
    Decode 64, X, Buffer 
    FF A, B, C, D, X(0), S11, -680876936 
    FF D, A, B, C, X(1), S12, -389564586 
    FF C, D, A, B, X(2), S13, 606105819 
    FF B, C, D, A, X(3), S14, -1044525330 
    FF A, B, C, D, X(4), S11, -176418897 
    FF D, A, B, C, X(5), S12, 1200080426 
    FF C, D, A, B, X(6), S13, -1473231341 
    FF B, C, D, A, X(7), S14, -45705983 
    FF A, B, C, D, X(8), S11, 1770035416 
    FF D, A, B, C, X(9), S12, -1958414417 
    FF C, D, A, B, X(10), S13, -42063 
    FF B, C, D, A, X(11), S14, -1990404162 
    FF A, B, C, D, X(12), S11, 1804603682 
    FF D, A, B, C, X(13), S12, -40341101 
    FF C, D, A, B, X(14), S13, -1502002290 
    FF B, C, D, A, X(15), S14, 1236535329 

    GG A, B, C, D, X(1), S21, -165796510 
    GG D, A, B, C, X(6), S22, -1069501632 
    GG C, D, A, B, X(11), S23, 643717713 
    GG B, C, D, A, X(0), S24, -373897302 
    GG A, B, C, D, X(5), S21, -701558691 
    GG D, A, B, C, X(10), S22, 38016083 
    GG C, D, A, B, X(15), S23, -660478335 
    GG B, C, D, A, X(4), S24, -405537848 
    GG A, B, C, D, X(9), S21, 568446438 
    GG D, A, B, C, X(14), S22, -1019803690 
    GG C, D, A, B, X(3), S23, -187363961 
    GG B, C, D, A, X(8), S24, 1163531501 
    GG A, B, C, D, X(13), S21, -1444681467 
    GG D, A, B, C, X(2), S22, -51403784 
    GG C, D, A, B, X(7), S23, 1735328473 
    GG B, C, D, A, X(12), S24, -1926607734 

    HH A, B, C, D, X(5), S31, -378558 
    HH D, A, B, C, X(8), S32, -2022574463 
    HH C, D, A, B, X(11), S33, 1839030562 
    HH B, C, D, A, X(14), S34, -35309556 
    HH A, B, C, D, X(1), S31, -1530992060 
    HH D, A, B, C, X(4), S32, 1272893353 
    HH C, D, A, B, X(7), S33, -155497632 
    HH B, C, D, A, X(10), S34, -1094730640 
    HH A, B, C, D, X(13), S31, 681279174 
    HH D, A, B, C, X(0), S32, -358537222 
    HH C, D, A, B, X(3), S33, -722521979 
    HH B, C, D, A, X(6), S34, 76029189 
    HH A, B, C, D, X(9), S31, -640364487 
    HH D, A, B, C, X(12), S32, -421815835 
    HH C, D, A, B, X(15), S33, 530742520 
    HH B, C, D, A, X(2), S34, -995338651 

    II A, B, C, D, X(0), S41, -198630844 
    II D, A, B, C, X(7), S42, 1126891415 
    II C, D, A, B, X(14), S43, -1416354905 
    II B, C, D, A, X(5), S44, -57434055 
    II A, B, C, D, X(12), S41, 1700485571 
    II D, A, B, C, X(3), S42, -1894986606 
    II C, D, A, B, X(10), S43, -1051523 
    II B, C, D, A, X(1), S44, -2054922799 
    II A, B, C, D, X(8), S41, 1873313359 
    II D, A, B, C, X(15), S42, -30611744 
    II C, D, A, B, X(6), S43, -1560198380 
    II B, C, D, A, X(13), S44, 1309151649 
    II A, B, C, D, X(4), S41, -145523070 
    II D, A, B, C, X(11), S42, -1120210379 
    II C, D, A, B, X(2), S43, 718787259 
    II B, C, D, A, X(9), S44, -343485551 

    State(1) = LongOverflowAdd(State(1), A) 
    State(2) = LongOverflowAdd(State(2), B) 
    State(3) = LongOverflowAdd(State(3), C) 
    State(4) = LongOverflowAdd(State(4), D) 
End Sub 

Private Sub Decode(Length As Integer, OutputBuffer() As Long, InputBuffer() As Byte) 
    Dim intDblIndex As Integer, intByteIndex As Integer, dblSum As Double 
    For intByteIndex = 0 To Length - 1 Step 4 
        dblSum = InputBuffer(intByteIndex) + InputBuffer(intByteIndex + 1) * 256# + InputBuffer(intByteIndex + 2) * 65536# + InputBuffer(intByteIndex + 3) * 16777216# 
        OutputBuffer(intDblIndex) = UnsignedToLong(dblSum) 
        intDblIndex = intDblIndex + 1 
    Next intByteIndex 
End Sub 
Private Function FF(A As Long, B As Long, C As Long, D As Long, X As Long, S As Long, ac As Long) As Long 
    A = LongOverflowAdd4(A, (B And C) Or (Not (B) And D), X, ac) 
    A = LongLeftRotate(A, S) 
    A = LongOverflowAdd(A, B) 
End Function 
Private Function GG(A As Long, B As Long, C As Long, D As Long, X As Long, S As Long, ac As Long) As Long 
    A = LongOverflowAdd4(A, (B And D) Or (C And Not (D)), X, ac) 
    A = LongLeftRotate(A, S) 
    A = LongOverflowAdd(A, B) 
End Function 
Private Function HH(A As Long, B As Long, C As Long, D As Long, X As Long, S As Long, ac As Long) As Long 
    A = LongOverflowAdd4(A, B Xor C Xor D, X, ac) 
    A = LongLeftRotate(A, S) 
    A = LongOverflowAdd(A, B) 
End Function 
Private Function II(A As Long, B As Long, C As Long, D As Long, X As Long, S As Long, ac As Long) As Long 
    A = LongOverflowAdd4(A, C Xor (B Or Not (D)), X, ac) 
    A = LongLeftRotate(A, S) 
    A = LongOverflowAdd(A, B) 
End Function 

Function LongLeftRotate(value As Long, Bits As Long) As Long 
    Dim lngSign As Long, lngI As Long 
    Bits = Bits Mod 32 
    If Bits = 0 Then LongLeftRotate = value: Exit Function 
    For lngI = 1 To Bits 
        lngSign = value And &HC0000000 
        value = (value And &H3FFFFFFF) * 2 
        value = value Or ((lngSign < 0) And 1) Or (CBool(lngSign And &H40000000) And &H80000000) 
    Next 
    LongLeftRotate = value 
End Function 
Private Function LongOverflowAdd(Val1 As Long, Val2 As Long) As Long 
    Dim lngHighWord As Long, lngLowWord As Long, lngOverflow As Long 
    lngLowWord = (Val1 And &HFFFF&) + (Val2 And &HFFFF&) 
    lngOverflow = lngLowWord / 65536 
    lngHighWord = (((Val1 And &HFFFF0000) / 65536) + ((Val2 And &HFFFF0000) / 65536) + lngOverflow) And &HFFFF& 
    LongOverflowAdd = UnsignedToLong((lngHighWord * 65536#) + (lngLowWord And &HFFFF&)) 
End Function 
Private Function LongOverflowAdd4(Val1 As Long, Val2 As Long, val3 As Long, val4 As Long) As Long 
    Dim lngHighWord As Long, lngLowWord As Long, lngOverflow As Long 
    lngLowWord = (Val1 And &HFFFF&) + (Val2 And &HFFFF&) + (val3 And &HFFFF&) + (val4 And &HFFFF&) 
    lngOverflow = lngLowWord / 65536 
    lngHighWord = (((Val1 And &HFFFF0000) / 65536) + ((Val2 And &HFFFF0000) / 65536) + ((val3 And &HFFFF0000) / 65536) + ((val4 And &HFFFF0000) / 65536) + lngOverflow) And &HFFFF& 
    LongOverflowAdd4 = UnsignedToLong((lngHighWord * 65536#) + (lngLowWord And &HFFFF&)) 
End Function 

Private Function UnsignedToLong(value As Double) As Long 
    If value < 0 Or value >= OFFSET_4 Then Error 6 
    If value <= MAXINT_4 Then UnsignedToLong = value Else UnsignedToLong = value - OFFSET_4 
End Function 
Private Function LongToUnsigned(value As Long) As Double 
    If value < 0 Then LongToUnsigned = value + OFFSET_4 Else LongToUnsigned = value 
End Function 
模块代码结束
在窗体中调用md5_string_calc() 实现计算 
------------------VB代码结束--------------------------

Delphi代码举例:
-----------------------MD5.PAS--------------------------------
unit MD5unit;

interface
uses Cryptcon, SysUtils, Classes, Controls;


Type
ULONG32 = record
 LoWord16: WORD;
 HiWord16: WORD;
end;

PULONG32 = ^ULONG32;
PLong = ^LongInt;

hashDigest = record
  A: Longint;
  B: Longint;
  C: Longint;
  D: Longint;
end;{hashArray}

PTR_Hash = ^hashDigest;


 TMD5 = class(TComponent)
 Private
 { Private declarations }




  FType : TSourceType;                     {Source type, whether its a file or ByteArray, or
                                            a Pascal String}
  FInputFilePath: String;                  {Full Path to Input File}
  FInputArray: PByte;                      {Point to input array}
  FInputString: String;                    {Input String}
  FOutputDigest: PTR_Hash;                 {output MD5 Digest}
  FSourceLength: LongInt;                  {input length in BYTES}
  FActiveBlock: Array[0..15] of LongInt;   {the 64Byte block being transformed}
  FA, FB, FC, FD, FAA, FBB, FCC, FDD: LongInt;
  {FA..FDD are used during Step 4, the transform.  I made them part of the
   Object to cut down on time used to pass variables.}
  FpA, FpB, FpC, FpD: PLong;
  {FIXME! do we need these, or just use the '@' operator?}
  {Put in for readability}
  {FF, GG, HH, II are used in Step 4, the transform}
  Procedure FF(a, b, c, d, x: Pointer; s: BYTE; ac: Longint);
  Procedure GG(a, b, c, d, x: Pointer; s: BYTE; ac: Longint);
  Procedure HH(a, b, c, d, x: Pointer; s: BYTE; ac: Longint);
  Procedure II(a, b, c, d, x: Pointer; s: BYTE; ac: Longint);


 protected
    { Protected declarations }

 public
    { Public declarations }
  {Initialize is used in Step 3, this fills FA..FD with init. values
   and points FpA..FpD to FA..FD}
  Procedure MD5_Initialize;
  {this is where all the magic happens}
  Procedure MD5_Transform;
  Procedure MD5_Finish;
  Procedure MD5_Hash_Bytes;
{  Procedure MD5_Hash_String;(Pascal Style strings???)}
  Procedure MD5_Hash_File;
  {This procedure sends the data 64Bytes at a time to MD5_Transform}
  Procedure MD5_Hash;

  Property pInputArray: PByte read FInputArray write FInputArray;
  Property pOutputArray: PTR_Hash read FOutputDigest write FOutputDigest;{!!See FOutputArray}
 Published
  Property InputType: TSourceType read FType write FType;
  Property InputFilePath: String read FInputFilePath write FInputFilePath;
  Property InputString: String read FInputString write FInputString;
  Property InputLength: LongInt read FSourceLength write FSourceLength;

end;{TMD5}


 procedure Register;{register the component to the Delphi toolbar}


Const
{Constants for MD5Transform routine.}
 S11 = 7;
 S12 = 12;
 S13 = 17;
 S14 = 22;
 S21 = 5;
 S22 = 9;
 S23 = 14;
 S24 = 20;
 S31 = 4;
 S32 = 11;
 S33 = 16;
 S34 = 23;
 S41 = 6;
 S42 = 10;
 S43 = 15;
 S44 = 21;

implementation



Function ROL(A: Longint; Amount: BYTE): Longint; Assembler;
asm
 mov cl, Amount
 rol eax, cl
end;



procedure Register;
  {Registers the Component to the toobar, on the tab named 'Crypto'}
  {Now all a Delphi programmer needs to do is drag n drop to have
   Blowfish encryption}
begin
  RegisterComponents('Crypto', [TMD5]);
end;

Procedure TMD5.MD5_Initialize;
var
 a, b, c, d: LongInt;
begin
 a := $67452301; b:=$efcdab89; c:=$98badcfe; d:=$10325476;
 Move(a, FA, 4); FpA := @FA;
 Move(b, FB, 4); FpB := @FB;
 Move(c, FC, 4); FpC := @FC;
 Move(d, FD, 4); FpD := @FD;
end;{MD5_Initialize}

Procedure TMD5.FF(a, b, c, d, x: Pointer; s: BYTE; ac: Longint);
{Purpose:  Round 1 of the Transform.
           Equivalent to a = b + ((a + F(b,c,d) + x + ac) <<< s)
           Where F(b,c,d) = b And c Or Not(b) And d
}
var
 Fret: LongInt;
begin
 Fret := ((PLong(b)^) And (PLong(c)^)) Or ((Not(PLong(b)^)) And (PLong(d)^));
 PLong(a)^ := PLong(a)^ + Fret + PLong(x)^ + ac;
 {NOW DO THE ROTATE LEFT}
 LongInt(a^):= ROL(LongInt(a^), s);
 {LongInt(a^):= ( LongInt(a^) SHL s) Or (LongInt(a^) SHR (32-(s)) );}
 Inc(PLong(a)^, PLong(b)^);
end;{FF}

Procedure TMD5.GG(a, b, c, d, x: Pointer; s: BYTE; ac: Longint);
{Purpose:  Round 2 of the Transform.
           Equivalent to a = b + ((a + G(b,c,d) + x + ac) <<< s)
           Where G(b,c,d) = b And d Or c Not d
}
var
 Gret: LongInt;
begin
 Gret := (PLong(b)^ And PLong(d)^) Or ( PLong(c)^ And (Not PLong(d)^));
 PLong(a)^ := PLong(a)^ + Gret + PLong(x)^ + ac;
 LongInt(a^):= ROL(LongInt(a^), s);
 {LongInt(a^):= ( LongInt(a^) SHL s) Or (LongInt(a^) SHR (32-(s)) );}
 Inc(PLong(a)^, PLong(b)^);
end;{GG}

Procedure TMD5.HH(a, b, c, d, x: Pointer; s: BYTE; ac: Longint);
{Purpose:  Round 3 of the Transform.
           Equivalent to a = b + ((a + H(b,c,d) + x + ac) <<< s)
           Where H(b,c,d) = b Xor c Xor d
}
var
 Hret: LongInt;
begin
 Hret := PLong(b)^ Xor PLong(c)^ Xor PLong(d)^;
 PLong(a)^ := PLong(a)^ + Hret + PLong(x)^ + ac;
 LongInt(a^):= ROL(LongInt(a^), s);
 {LongInt(a^):= ( LongInt(a^) SHL s) Or (LongInt(a^) SHR (32-(s)) );}
 PLong(a)^ := PLong(b)^ + PLong(a)^;
end;{HH}

Procedure TMD5.II(a, b, c, d, x: Pointer; s: BYTE; ac: Longint);
{Purpose:  Round 4 of the Transform.
           Equivalent to a = b + ((a + I(b,c,d) + x + ac) <<< s)
           Where I(b,c,d) = C Xor (b Or Not(d))
}
var
 Iret: LongInt;
begin
 Iret := (PLong(c)^ Xor (PLong(b)^ Or (Not PLong(d)^)));
 PLong(a)^ := PLong(a)^ + Iret + PLong(x)^ + ac;
 LongInt(a^):= ROL(PLong(a)^, s );
{ LongInt(a^):= ( LongInt(a^) SHL s) Or (LongInt(a^) SHR (32-(s)) );}
 PLong(a)^ := PLong(b)^ + PLong(a)^;
end;{II}

Procedure TMD5.MD5_Transform;
{Purpose:  Perform Step 4 of the algorithm.  This is where all the important
           stuff happens.  This performs the rounds on a 64Byte Block.  This
           procedure should be called in a loop until all input data has been
           transformed.
}

begin
  FAA := FA;
  FBB := FB;
  FCC := FC;
  FDD := FD;

  { Round 1 }
  FF (FpA, FpB, FpC, FpD, @FActiveBlock[ 0], S11, $d76aa478); { 1 }
  FF (FpD, FpA, FpB, FpC, @FActiveBlock[ 1], S12, $e8c7b756); { 2 }
  FF (FpC, FpD, FpA, FpB, @FActiveBlock[ 2], S13, $242070db); { 3 }
  FF (FpB, FpC, FpD, FpA, @FActiveBlock[ 3], S14, $c1bdceee); { 4 }
  FF (FpA, FpB, FpC, FpD, @FActiveBlock[ 4], S11, $f57c0faf); { 5 }
  FF (FpD, FpA, FpB, FpC, @FActiveBlock[ 5], S12, $4787c62a); { 6 }
  FF (FpC, FpD, FpA, FpB, @FActiveBlock[ 6], S13, $a8304613); { 7 }
  FF (FpB, FpC, FpD, FpA, @FActiveBlock[ 7], S14, $fd469501); { 8 }
  FF (FpA, FpB, FpC, FpD, @FActiveBlock[ 8], S11, $698098d8); { 9 }
  FF (FpD, FpA, FpB, FpC, @FActiveBlock[ 9], S12, $8b44f7af); { 10 }
  FF (FpC, FpD, FpA, FpB, @FActiveBlock[10], S13, $ffff5bb1); { 11 }
  FF (FpB, FpC, FpD, FpA, @FActiveBlock[11], S14, $895cd7be); { 12 }
  FF (FpA, FpB, FpC, FpD, @FActiveBlock[12], S11, $6b901122); { 13 }
  FF (FpD, FpA, FpB, FpC, @FActiveBlock[13], S12, $fd987193); { 14 }
  FF (FpC, FpD, FpA, FpB, @FActiveBlock[14], S13, $a679438e); { 15 }
  FF (FpB, FpC, FpD, FpA, @FActiveBlock[15], S14, $49b40821); { 16 }

 { Round 2 }
  GG (FpA, FpB, FpC, FpD, @FActiveBlock[ 1], S21, $f61e2562); { 17 }
  GG (FpD, FpA, FpB, FpC, @FActiveBlock[ 6], S22, $c040b340); { 18 }
  GG (FpC, FpD, FpA, FpB, @FActiveBlock[11], S23, $265e5a51); { 19 }
  GG (FpB, FpC, FpD, FpA, @FActiveBlock[ 0], S24, $e9b6c7aa); { 20 }
  GG (FpA, FpB, FpC, FpD, @FActiveBlock[ 5], S21, $d62f105d); { 21 }
  GG (FpD, FpA, FpB, FpC, @FActiveBlock[10], S22,  $2441453); { 22 }
  GG (FpC, FpD, FpA, FpB, @FActiveBlock[15], S23, $d8a1e681); { 23 }
  GG (FpB, FpC, FpD, FpA, @FActiveBlock[ 4], S24, $e7d3fbc8); { 24 }
  GG (FpA, FpB, FpC, FpD, @FActiveBlock[ 9], S21, $21e1cde6); { 25 }
  GG (FpD, FpA, FpB, FpC, @FActiveBlock[14], S22, $c33707d6); { 26 }
  GG (FpC, FpD, FpA, FpB, @FActiveBlock[ 3], S23, $f4d50d87); { 27 }
  GG (FpB, FpC, FpD, FpA, @FActiveBlock[ 8], S24, $455a14ed); { 28 }
  GG (FpA, FpB, FpC, FpD, @FActiveBlock[13], S21, $a9e3e905); { 29 }
  GG (FpD, FpA, FpB, FpC, @FActiveBlock[ 2], S22, $fcefa3f8); { 30 }
  GG (FpC, FpD, FpA, FpB, @FActiveBlock[ 7], S23, $676f02d9); { 31 }
  GG (FpB, FpC, FpD, FpA, @FActiveBlock[12], S24, $8d2a4c8a); { 32 }

  { Round 3 }
  HH (FpA, FpB, FpC, FpD, @FActiveBlock[ 5], S31, $fffa3942); { 33 }
  HH (FpD, FpA, FpB, FpC, @FActiveBlock[ 8], S32, $8771f681); { 34 }
  HH (FpC, FpD, FpA, FpB, @FActiveBlock[11], S33, $6d9d6122); { 35 }
  HH (FpB, FpC, FpD, FpA, @FActiveBlock[14], S34, $fde5380c); { 36 }
  HH (FpA, FpB, FpC, FpD, @FActiveBlock[ 1], S31, $a4beea44); { 37 }
  HH (FpD, FpA, FpB, FpC, @FActiveBlock[ 4], S32, $4bdecfa9); { 38 }
  HH (FpC, FpD, FpA, FpB, @FActiveBlock[ 7], S33, $f6bb4b60); { 39 }
  HH (FpB, FpC, FpD, FpA, @FActiveBlock[10], S34, $bebfbc70); { 40 }
  HH (FpA, FpB, FpC, FpD, @FActiveBlock[13], S31, $289b7ec6); { 41 }
  HH (FpD, FpA, FpB, FpC, @FActiveBlock[ 0], S32, $eaa127fa); { 42 }
  HH (FpC, FpD, FpA, FpB, @FActiveBlock[ 3], S33, $d4ef3085); { 43 }
  HH (FpB, FpC, FpD, FpA, @FActiveBlock[ 6], S34,  $4881d05); { 44 }
  HH (FpA, FpB, FpC, FpD, @FActiveBlock[ 9], S31, $d9d4d039); { 45 }
  HH (FpD, FpA, FpB, FpC, @FActiveBlock[12], S32, $e6db99e5); { 46 }
  HH (FpC, FpD, FpA, FpB, @FActiveBlock[15], S33, $1fa27cf8); { 47 }
  HH (FpB, FpC, FpD, FpA, @FActiveBlock[ 2], S34, $c4ac5665); { 48 }

  { Round 4 }
  II (FpA, FpB, FpC, FpD, @FActiveBlock[ 0], S41, $f4292244); { 49 }
  II (FpD, FpA, FpB, FpC, @FActiveBlock[ 7], S42, $432aff97); { 50 }
  II (FpC, FpD, FpA, FpB, @FActiveBlock[14], S43, $ab9423a7); { 51 }
  II (FpB, FpC, FpD, FpA, @FActiveBlock[ 5], S44, $fc93a039); { 52 }
  II (FpA, FpB, FpC, FpD, @FActiveBlock[12], S41, $655b59c3); { 53 }
  II (FpD, FpA, FpB, FpC, @FActiveBlock[ 3], S42, $8f0ccc92); { 54 }
  II (FpC, FpD, FpA, FpB, @FActiveBlock[10], S43, $ffeff47d); { 55 }
  II (FpB, FpC, FpD, FpA, @FActiveBlock[ 1], S44, $85845dd1); { 56 }
  II (FpA, FpB, FpC, FpD, @FActiveBlock[ 8], S41, $6fa87e4f); { 57 }
  II (FpD, FpA, FpB, FpC, @FActiveBlock[15], S42, $fe2ce6e0); { 58 }
  II (FpC, FpD, FpA, FpB, @FActiveBlock[ 6], S43, $a3014314); { 59 }
  II (FpB, FpC, FpD, FpA, @FActiveBlock[13], S44, $4e0811a1); { 60 }
  II (FpA, FpB, FpC, FpD, @FActiveBlock[ 4], S41, $f7537e82); { 61 }
  II (FpD, FpA, FpB, FpC, @FActiveBlock[11], S42, $bd3af235); { 62 }
  II (FpC, FpD, FpA, FpB, @FActiveBlock[ 2], S43, $2ad7d2bb); { 63 }
  II (FpB, FpC, FpD, FpA, @FActiveBlock[ 9], S44, $eb86d391); { 64 }

  Inc(FA, FAA);
  Inc(FB, FBB);
  Inc(FC, FCC);
  Inc(FD, FDD);
  { Zeroize sensitive information}
  FillChar(FActiveBlock, SizeOf(FActiveBlock), #0);
end;{TMD5.MD5_Transform}

Procedure TMD5.MD5_Hash;
var
 pStr: PChar;
begin
  MD5_Initialize;
  case FType of
   SourceFile:
   begin
    MD5_Hash_File;
   end;{SourceFile}
   SourceByteArray:
   begin
    MD5_Hash_Bytes;
   end;{SourceByteArray}
   SourceString:
   begin
    {Convert Pascal String to Byte Array}

    pStr := StrAlloc(Length(FInputString) + 1);
    try {protect dyanmic memory allocation}
    StrPCopy(pStr, FInputString);


    FSourceLength := Length(FInputString);
    FInputArray := Pointer(pStr);
    MD5_Hash_Bytes;

    finally
     StrDispose(pStr);
    end;

   end;{SourceString}
  end;{case}
  MD5_Finish;
end;{TMD5.MD5_Hash}

Procedure TMD5.MD5_Hash_Bytes;
var
  Buffer: array[0..4159] of Byte;
  Count64: Comp;
  index: longInt;
begin
  Move(FInputArray^, Buffer, FSourceLength);
  Count64 := FSourceLength * 8;     {Save the Length(in bits) before padding}
  Buffer[FSourceLength] := $80;     {Must always pad with at least a '1'}
  inc(FSourceLength);

  while (FSourceLength mod 64)<>56 do begin
   Buffer[FSourceLength] := 0;
   Inc(FSourceLength);
  end;
  Move(Count64,Buffer[FSourceLength],SizeOf(Count64){This better be 64bits});
  index := 0;
  Inc(FSourceLength, 8);
  repeat
    Move(Buffer[Index], FActiveBlock, 64);
    {Flip bytes here on Mac??}
    MD5_Transform;
    Inc(Index,64);
  until Index = FSourceLength;
end;{TMD5.Hash_Bytes}

Procedure TMD5.MD5_Hash_File;
var
  Buffer:array[0..4159] of BYTE;
  InputFile: File;
  Count64: Comp;
  DoneFile : Boolean;
  Index: LongInt;
  NumRead: integer ;
begin
DoneFile := False;

 AssignFile(InputFile, FInputFilePath);



Reset(InputFile, 1);
Count64 := 0;
repeat
    BlockRead(InputFile,Buffer,4096,NumRead);
    Count64 := Count64 + NumRead;
    if NumRead<>4096 {reached end of file}
      then begin
          Buffer[NumRead]:= $80;
          Inc(NumRead);
          while (NumRead mod 64)<>56
            do begin
               Buffer[ NumRead ] := 0;
               Inc(NumRead);
              end;
          Count64 := Count64 * 8;
          Move(Count64,Buffer[NumRead],8);
          Inc(NumRead,8);
          DoneFile := True;
        end;
    Index := 0;
    repeat
     Move(Buffer[Index], FActiveBlock, 64);
     {Flip bytes here on a Mac(I think)}

     MD5_Transform;
     Inc(Index,64);
    until Index = NumRead;
  until DoneFile;

  CloseFile(InputFile);

end;{TMD5.MD5_Hash_File}


Procedure TMD5.MD5_Finish;
begin
 FOutputDigest^.A := LongInt(FpA^);
 FOutputDigest^.B := LongInt(FpB^);
 FOutputDigest^.C := LongInt(FpC^);
 FOutputDigest^.D := LongInt(FpD^);
end;
end.
-------------------------Delphi代码结束------------------------

结束语:

洋洋洒洒的一大篇可是我查找了不少资料才写出来,大概可以当成我们学校的 Computer Assignment了 
^_^ 感谢大家能耐心的看完,最后给大家出到题吧,大家可以试试自己的运气啊,就是: “51E5D4BD3323A02CCCDD0472AE2DC20B”这组数是我通过MD5算法加密一组字符串后产生的结果,大家猜猜看我加密的初始字 符串是什么? 提示一下 -- 原始字符串加上空格一共有20位。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值