MD5算法比较特别,最适合用汇编语言来写,好多高级语言对之无能无力或效率极低。
比如我最开始尝试用Python和Euphoria编写,发现不太容易。相比而言,C#作为C家簇
中新兴的一门.net语言,功能比较全面。花了一晚上的工夫终于用C#最先实现了MD5。
主要是由于对算法的一些细节不太注意,结果输出总是不对,调试了好长时间。 
InBlock.gifusing System;
InBlock.gifusing System.Collections.Generic;
InBlock.gifusing System.Text;
InBlock.gifusing System.Collections;    
InBlock.gifusing System.IO;    
InBlock.gif
InBlock.gifnamespace SocketHttpTest.BaseC.MD5
InBlock.gif...{
InBlock.gif        public class MD5
InBlock.gif        ...{
InBlock.gif                //static state variables    
InBlock.gif                private static UInt32 A;
InBlock.gif                private static UInt32 B;
InBlock.gif                private static UInt32 C;
InBlock.gif                private static UInt32 D;
InBlock.gif
InBlock.gif                //number of bits to rotate in tranforming    
InBlock.gif                private const int S11 = 7;
InBlock.gif                private const int S12 = 12;
InBlock.gif                private const int S13 = 17;
InBlock.gif                private const int S14 = 22;
InBlock.gif                private const int S21 = 5;
InBlock.gif                private const int S22 = 9;
InBlock.gif                private const int S23 = 14;
InBlock.gif                private const int S24 = 20;
InBlock.gif                private const int S31 = 4;
InBlock.gif                private const int S32 = 11;
InBlock.gif                private const int S33 = 16;
InBlock.gif                private const int S34 = 23;
InBlock.gif                private const int S41 = 6;
InBlock.gif                private const int S42 = 10;
InBlock.gif                private const int S43 = 15;
InBlock.gif                private const int S44 = 21;
InBlock.gif
InBlock.gif
InBlock.gif                /**//* F, G, H and I are basic MD5 functions.    
InBlock.gif                 * 四个非线性函数:    
InBlock.gif                 *    
InBlock.gif                 * F(X,Y,Z) =(X&Y)|((~X)&Z)    
InBlock.gif                 * G(X,Y,Z) =(X&Z)|(Y&(~Z))    
InBlock.gif                 * H(X,Y,Z) =X^Y^Z    
InBlock.gif                 * I(X,Y,Z)=Y^(X|(~Z))    
InBlock.gif                 *    
InBlock.gif                 * (&与,|或,~非,^异或)    
InBlock.gif                 */

InBlock.gif                private static UInt32 F(UInt32 x, UInt32 y, UInt32 z)
InBlock.gif                ...{
InBlock.gif                        return (x & y) | ((~x) & z);
InBlock.gif                }
InBlock.gif                private static UInt32 G(UInt32 x, UInt32 y, UInt32 z)
InBlock.gif                ...{
InBlock.gif                        return (x & z) | (y & (~z));
InBlock.gif                }
InBlock.gif                private static UInt32 H(UInt32 x, UInt32 y, UInt32 z)
InBlock.gif                ...{
InBlock.gif                        return x ^ y ^ z;
InBlock.gif                }
InBlock.gif                private static UInt32 I(UInt32 x, UInt32 y, UInt32 z)
InBlock.gif                ...{
InBlock.gif                        return y ^ (x | (~z));
InBlock.gif                }
InBlock.gif
InBlock.gif                /**//* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.    
InBlock.gif                 * Rotation is separate from addition to prevent recomputation.    
InBlock.gif                 */

InBlock.gif                private static void FF(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)
InBlock.gif                ...{
InBlock.gif                        a = a + F(b, c, d) + mj + ti;
InBlock.gif                        a = a << s | a >> (32 - s);
InBlock.gif                        a += b;
InBlock.gif                }
InBlock.gif                private static void GG(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)
InBlock.gif                ...{
InBlock.gif                        a = a + G(b, c, d) + mj + ti;
InBlock.gif                        a = a << s | a >> (32 - s);
InBlock.gif                        a += b;
InBlock.gif                }
InBlock.gif                private static void HH(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)
InBlock.gif                ...{
InBlock.gif                        a = a + H(b, c, d) + mj + ti;
InBlock.gif                        a = a << s | a >> (32 - s);
InBlock.gif                        a += b;
InBlock.gif                }
InBlock.gif                private static void II(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)
InBlock.gif                ...{
InBlock.gif                        a = a + I(b, c, d) + mj + ti;
InBlock.gif                        a = a << s | a >> (32 - s);
InBlock.gif                        a += b;
InBlock.gif                }
InBlock.gif
InBlock.gif                private static void MD5_Init()
InBlock.gif                ...{
InBlock.gif                        A = 0x67452301;    //in memory, this is 0x01234567    
InBlock.gif                        B = 0xefcdab89;    //in memory, this is 0x89abcdef    
InBlock.gif                        C = 0x98badcfe;    //in memory, this is 0xfedcba98    
InBlock.gif                        D = 0x10325476;    //in memory, this is 0x76543210    
InBlock.gif                }
InBlock.gif
InBlock.gif                private static UInt32[] MD5_Append(byte[] input)
InBlock.gif                ...{
InBlock.gif                        int zeros = 0;
InBlock.gif                        int ones = 1;
InBlock.gif                        int size = 0;
InBlock.gif                        int n = input.Length;
InBlock.gif                        int m = n % 64;
InBlock.gif                        if (m < 56)
InBlock.gif                        ...{
InBlock.gif                                zeros = 55 - m;
InBlock.gif                                size = n - m + 64;
InBlock.gif                        }
InBlock.gif                        else if (m == 56)
InBlock.gif                        ...{
InBlock.gif                                zeros = 0;
InBlock.gif                                ones = 0;
InBlock.gif                                size = n + 8;
InBlock.gif                        }
InBlock.gif                        else
InBlock.gif                        ...{
InBlock.gif                                zeros = 63 - m + 56;
InBlock.gif                                size = n + 64 - m + 64;
InBlock.gif                        }
InBlock.gif
InBlock.gif                        ArrayList bs = new ArrayList(input);
InBlock.gif                        if (ones == 1)
InBlock.gif                        ...{
InBlock.gif                                bs.Add((byte)0x80); // 0x80 = 000000    
InBlock.gif                        }
InBlock.gif                        for (int i = 0; i < zeros; i++)
InBlock.gif                        ...{
InBlock.gif                                bs.Add((byte)0);
InBlock.gif                        }
InBlock.gif
InBlock.gif                        UInt64 N = (UInt64)n * 8;
InBlock.gif                        byte h1 = (byte)(N & 0xFF);
InBlock.gif                        byte h2 = (byte)((N >> 8) & 0xFF);
InBlock.gif                        byte h3 = (byte)((N >> 16) & 0xFF);
InBlock.gif                        byte h4 = (byte)((N >> 24) & 0xFF);
InBlock.gif                        byte h5 = (byte)((N >> 32) & 0xFF);
InBlock.gif                        byte h6 = (byte)((N >> 40) & 0xFF);
InBlock.gif                        byte h7 = (byte)((N >> 48) & 0xFF);
InBlock.gif                        byte h8 = (byte)(N >> 56);
InBlock.gif                        bs.Add(h1);
InBlock.gif                        bs.Add(h2);
InBlock.gif                        bs.Add(h3);
InBlock.gif                        bs.Add(h4);
InBlock.gif                        bs.Add(h5);
InBlock.gif                        bs.Add(h6);
InBlock.gif                        bs.Add(h7);
InBlock.gif                        bs.Add(h8);
InBlock.gif                        byte[] ts = (byte[])bs.ToArray(typeof(byte));
InBlock.gif
InBlock.gif                        /**//* Decodes input (byte[]) into output (UInt32[]). Assumes len is    
InBlock.gif                         * a multiple of 4.    
InBlock.gif                         */

InBlock.gif                        UInt32[] output = new UInt32[size / 4];
InBlock.gif                        for (Int64 i = 0, j = 0; i < size; j++, i += 4)
InBlock.gif                        ...{
InBlock.gif                                
InBlock.gif                                output[j] = (UInt32)(ts[i] | ts[i + 1] << 8 | ts[i + 2] << 16 | ts[i + 3] << 24);
InBlock.gif                        }
InBlock.gif                        return output;
InBlock.gif                }
InBlock.gif                private static UInt32[] MD5_Trasform(UInt32[] x)
InBlock.gif                ...{
InBlock.gif
InBlock.gif                        UInt32 a, b, c, d;
InBlock.gif
InBlock.gif                        for (int k = 0; k < x.Length; k += 16)
InBlock.gif                        ...{
InBlock.gif                                a = A;
InBlock.gif                                b = B;
InBlock.gif                                c = C;
InBlock.gif                                d = D;
InBlock.gif
InBlock.gif                                /**//* Round 1 */
InBlock.gif                                FF(ref a, b, c, d, x[k + 0], S11, 0xd76aa478); /**//* 1 */
InBlock.gif                                FF(ref d, a, b, c, x[k + 1], S12, 0xe8c7b756); /**//* 2 */
InBlock.gif                                FF(ref c, d, a, b, x[k + 2], S13, 0x242070db); /**//* 3 */
InBlock.gif                                FF(ref b, c, d, a, x[k + 3], S14, 0xc1bdceee); /**//* 4 */
InBlock.gif                                FF(ref a, b, c, d, x[k + 4], S11, 0xf57c0faf); /**//* 5 */
InBlock.gif                                FF(ref d, a, b, c, x[k + 5], S12, 0x4787c62a); /**//* 6 */
InBlock.gif                                FF(ref c, d, a, b, x[k + 6], S13, 0xa8304613); /**//* 7 */
InBlock.gif                                FF(ref b, c, d, a, x[k + 7], S14, 0xfd469501); /**//* 8 */
InBlock.gif                                FF(ref a, b, c, d, x[k + 8], S11, 0x698098d8); /**//* 9 */
InBlock.gif                                FF(ref d, a, b, c, x[k + 9], S12, 0x8b44f7af); /**//* 10 */
InBlock.gif                                FF(ref c, d, a, b, x[k + 10], S13, 0xffff5bb1); /**//* 11 */
InBlock.gif                                FF(ref b, c, d, a, x[k + 11], S14, 0x895cd7be); /**//* 12 */
InBlock.gif                                FF(ref a, b, c, d, x[k + 12], S11, 0x6b901122); /**//* 13 */
InBlock.gif                                FF(ref d, a, b, c, x[k + 13], S12, 0xfd987193); /**//* 14 */
InBlock.gif                                FF(ref c, d, a, b, x[k + 14], S13, 0xa679438e); /**//* 15 */
InBlock.gif                                FF(ref b, c, d, a, x[k + 15], S14, 0x49b40821); /**//* 16 */
InBlock.gif
InBlock.gif                                /**//* Round 2 */
InBlock.gif                                GG(ref a, b, c, d, x[k + 1], S21, 0xf61e2562); /**//* 17 */
InBlock.gif                                GG(ref d, a, b, c, x[k + 6], S22, 0xc040b340); /**//* 18 */
InBlock.gif                                GG(ref c, d, a, b, x[k + 11], S23, 0x265e5a51); /**//* 19 */
InBlock.gif                                GG(ref b, c, d, a, x[k + 0], S24, 0xe9b6c7aa); /**//* 20 */
InBlock.gif                                GG(ref a, b, c, d, x[k + 5], S21, 0xd62f105d); /**//* 21 */
InBlock.gif                                GG(ref d, a, b, c, x[k + 10], S22, 0x2441453); /**//* 22 */
InBlock.gif                                GG(ref c, d, a, b, x[k + 15], S23, 0xd8a1e681); /**//* 23 */
InBlock.gif                                GG(ref b, c, d, a, x[k + 4], S24, 0xe7d3fbc8); /**//* 24 */
InBlock.gif                                GG(ref a, b, c, d, x[k + 9], S21, 0x21e1cde6); /**//* 25 */
InBlock.gif                                GG(ref d, a, b, c, x[k + 14], S22, 0xc33707d6); /**//* 26 */
InBlock.gif                                GG(ref c, d, a, b, x[k + 3], S23, 0xf4d50d87); /**//* 27 */
InBlock.gif                                GG(ref b, c, d, a, x[k + 8], S24, 0x455a14ed); /**//* 28 */
InBlock.gif                                GG(ref a, b, c, d, x[k + 13], S21, 0xa9e3e905); /**//* 29 */
InBlock.gif                                GG(ref d, a, b, c, x[k + 2], S22, 0xfcefa3f8); /**//* 30 */
InBlock.gif                                GG(ref c, d, a, b, x[k + 7], S23, 0x676f02d9); /**//* 31 */
InBlock.gif                                GG(ref b, c, d, a, x[k + 12], S24, 0x8d2a4c8a); /**//* 32 */
InBlock.gif
InBlock.gif                                /**//* Round 3 */
InBlock.gif                                HH(ref a, b, c, d, x[k + 5], S31, 0xfffa3942); /**//* 33 */
InBlock.gif                                HH(ref d, a, b, c, x[k + 8], S32, 0x8771f681); /**//* 34 */
InBlock.gif                                HH(ref c, d, a, b, x[k + 11], S33, 0x6d9d6122); /**//* 35 */
InBlock.gif                                HH(ref b, c, d, a, x[k + 14], S34, 0xfde5380c); /**//* 36 */
InBlock.gif                                HH(ref a, b, c, d, x[k + 1], S31, 0xa4beea44); /**//* 37 */
InBlock.gif                                HH(ref d, a, b, c, x[k + 4], S32, 0x4bdecfa9); /**//* 38 */
InBlock.gif                                HH(ref c, d, a, b, x[k + 7], S33, 0xf6bb4b60); /**//* 39 */
InBlock.gif                                HH(ref b, c, d, a, x[k + 10], S34, 0xbebfbc70); /**//* 40 */
InBlock.gif                                HH(ref a, b, c, d, x[k + 13], S31, 0x289b7ec6); /**//* 41 */
InBlock.gif                                HH(ref d, a, b, c, x[k + 0], S32, 0xeaa127fa); /**//* 42 */
InBlock.gif                                HH(ref c, d, a, b, x[k + 3], S33, 0xd4ef3085); /**//* 43 */
InBlock.gif                                HH(ref b, c, d, a, x[k + 6], S34, 0x4881d05); /**//* 44 */
InBlock.gif                                HH(ref a, b, c, d, x[k + 9], S31, 0xd9d4d039); /**//* 45 */
InBlock.gif                                HH(ref d, a, b, c, x[k + 12], S32, 0xe6db99e5); /**//* 46 */
InBlock.gif                                HH(ref c, d, a, b, x[k + 15], S33, 0x1fa27cf8); /**//* 47 */
InBlock.gif                                HH(ref b, c, d, a, x[k + 2], S34, 0xc4ac5665); /**//* 48 */
InBlock.gif
InBlock.gif                                /**//* Round 4 */
InBlock.gif                                II(ref a, b, c, d, x[k + 0], S41, 0xf4292244); /**//* 49 */
InBlock.gif                                II(ref d, a, b, c, x[k + 7], S42, 0x432aff97); /**//* 50 */
InBlock.gif                                II(ref c, d, a, b, x[k + 14], S43, 0xab9423a7); /**//* 51 */
InBlock.gif                                II(ref b, c, d, a, x[k + 5], S44, 0xfc93a039); /**//* 52 */
InBlock.gif                                II(ref a, b, c, d, x[k + 12], S41, 0x655b59c3); /**//* 53 */
InBlock.gif                                II(ref d, a, b, c, x[k + 3], S42, 0x8f0ccc92); /**//* 54 */
InBlock.gif                                II(ref c, d, a, b, x[k + 10], S43, 0xffeff47d); /**//* 55 */
InBlock.gif                                II(ref b, c, d, a, x[k + 1], S44, 0x85845dd1); /**//* 56 */
InBlock.gif                                II(ref a, b, c, d, x[k + 8], S41, 0x6fa87e4f); /**//* 57 */
InBlock.gif                                II(ref d, a, b, c, x[k + 15], S42, 0xfe2ce6e0); /**//* 58 */
InBlock.gif                                II(ref c, d, a, b, x[k + 6], S43, 0xa3014314); /**//* 59 */
InBlock.gif                                II(ref b, c, d, a, x[k + 13], S44, 0x4e0811a1); /**//* 60 */
InBlock.gif                                II(ref a, b, c, d, x[k + 4], S41, 0xf7537e82); /**//* 61 */
InBlock.gif                                II(ref d, a, b, c, x[k + 11], S42, 0xbd3af235); /**//* 62 */
InBlock.gif                                II(ref c, d, a, b, x[k + 2], S43, 0x2ad7d2bb); /**//* 63 */
InBlock.gif                                II(ref b, c, d, a, x[k + 9], S44, 0xeb86d391); /**//* 64 */
InBlock.gif
InBlock.gif                                A += a;
InBlock.gif                                B += b;
InBlock.gif                                C += c;
InBlock.gif                                D += d;
InBlock.gif                        }
InBlock.gif                        return new UInt32[] ...{ A, B, C, D };
InBlock.gif                }
InBlock.gif                public static byte[] MD5Array(byte[] input)
InBlock.gif                ...{
InBlock.gif                        MD5_Init();
InBlock.gif                        UInt32[] block = MD5_Append(input);
InBlock.gif                        UInt32[] bits = MD5_Trasform(block);
InBlock.gif
InBlock.gif                        /**//* Encodes bits (UInt32[]) into output (byte[]). Assumes len is    
InBlock.gif                         * a multiple of 4.    
InBlock.gif                                 */

InBlock.gif                        byte[] output = new byte[bits.Length * 4];
InBlock.gif                        for (int i = 0, j = 0; i < bits.Length; i++, j += 4)
InBlock.gif                        ...{
InBlock.gif                                
InBlock.gif                                output[j] = (byte)(bits[i] & 0xff);
InBlock.gif                                output[j + 1] = (byte)((bits[i] >> 8) & 0xff);
InBlock.gif                                output[j + 2] = (byte)((bits[i] >> 16) & 0xff);
InBlock.gif                                output[j + 3] = (byte)((bits[i] >> 24) & 0xff);
InBlock.gif                        }
InBlock.gif                        return output;
InBlock.gif                }
InBlock.gif
InBlock.gif                public static string ArrayToHexString(byte[] array, bool uppercase)
InBlock.gif                ...{
InBlock.gif                        string hexString = "";
InBlock.gif                        string format = "x2";
InBlock.gif                        if (uppercase)
InBlock.gif                        ...{
InBlock.gif                                format = "X2";
InBlock.gif                        }
InBlock.gif                        foreach (byte b in array)
InBlock.gif                        ...{
InBlock.gif                                hexString += b.ToString(format);
InBlock.gif                        }
InBlock.gif                        return hexString;
InBlock.gif                }
InBlock.gif
InBlock.gif                public static string MDString(string message)
InBlock.gif                ...{
InBlock.gif                        char[] c = message.ToCharArray();
InBlock.gif                        byte[] b = new byte[c.Length];
InBlock.gif                        for (int i = 0; i < c.Length; i++)
InBlock.gif                        ...{
InBlock.gif                                b[i] = (byte)c[i];
InBlock.gif                        }
InBlock.gif                        byte[] digest = MD5Array(b);
InBlock.gif                        return ArrayToHexString(digest, false);
InBlock.gif                }
InBlock.gif                public static string MDFile(string fileName)
InBlock.gif                ...{
InBlock.gif                        FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read);
InBlock.gif                        byte[] array = new byte[fs.Length];
InBlock.gif                        fs.Read(array, 0, (int)fs.Length);
InBlock.gif                        byte[] digest = MD5Array(array);
InBlock.gif                        fs.Close();
InBlock.gif                        return ArrayToHexString(digest, false);
InBlock.gif                }
InBlock.gif
InBlock.gif                public static string Test(string message)
InBlock.gif                ...{
InBlock.gif                        return " MD5 ("" + message + "") = " + MD5.MDString(message);
InBlock.gif                }
InBlock.gif                public static string TestSuite()
InBlock.gif                ...{
InBlock.gif                        string s = "";
InBlock.gif                        s += Test("");
InBlock.gif                        s += Test("a");
InBlock.gif                        s += Test("abc");
InBlock.gif                        s += Test("message digest");
InBlock.gif                        s += Test("abcdefghijklmnopqrstuvwxyz");
InBlock.gif                        s += Test("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
InBlock.gif                        s += Test("12345678901234567890123456789012345678901234567890123456789012345678901234567890");
InBlock.gif                        return s;
InBlock.gif                }
InBlock.gif        }
InBlock.gif}