飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 9584|回复: 13

MD5的介绍,算法以及实现

[复制链接]
  • TA的每日心情
    难过
    7 天前
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    发表于 2004-12-14 10:54:16 | 显示全部楼层 |阅读模式
    MD5的介绍,算法以及实现(第三次修正)
                                                                                                    Wrote By 娃娃/[CCG]


    前言:

    一次偶然的机会和破解界的朋友 -- Stkman大哥谈起了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);

    index = 0;
      }
      else
    i = 0;

      MD5_memcpy
    ((POINTER)&context->buffer[index], (POINTER)&input,
      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 & 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);
      }
    }

    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 = ((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 = input;
    }

    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) = (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位。

    ^_^  Bye!
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-3-14 23:34:18 | 显示全部楼层
    看不懂!!支持一下!!!!
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-4-14 14:51:47 | 显示全部楼层
    哎我只看到一堆乱码(E文不懂小学没毕业)
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-4-14 18:58:19 | 显示全部楼层
    提示: 作者被禁止或删除 内容自动屏蔽
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-4-20 12:02:19 | 显示全部楼层
    已经被山东的教授破解了啊
    PYG19周年生日快乐!
  • TA的每日心情
    奋斗
    2020-2-22 19:39
  • 签到天数: 114 天

    [LV.6]常住居民II

    发表于 2007-4-26 20:37:17 | 显示全部楼层
    完全看不明白.....
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2023-11-2 14:38
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2007-5-2 21:50:16 | 显示全部楼层
    慢慢学吧.没有达到这个地步啊.
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-6-2 17:35:06 | 显示全部楼层
    虽然看不懂,还是收藏下来,以后好好看
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-6-2 23:29:43 | 显示全部楼层
    还是以后慢慢看吧~~关注。。。收藏中。。。
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-6-7 07:14:57 | 显示全部楼层
    分析一下,呵呵
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表