发现网上的MD5程序大多都是错误的!

最近在研究MD5的时候,在网上也找了许多用C#描述的代码。发现所有的代码都是一样的。也查不出是出自哪里。
但是我通过大量数据的检测,发现在数据量为:64*n-8 n=1,2,3....时,得到的md5值都是错误的。出错的原因是补位的时候多补了一位,所以导致多计算了一组。

出错代码的地址有下:
http://www.md5sha1.com/md5cs.htm
http://tech.163.com/06/0106/22/26QKQN5F0009159F.html
http://blog.csdn.net/sxf_zero/archive/2007/02/18/1511683.aspx

http://www.taiwanren.com/blog/article.asp?id=78

下面是我自己写的一个可以计算一个stream里面任意部分数据MD5值的类,通过大量数据检测,没有发现错误。
我的这个类,跟 System.Security.Cryptography.MD5相比,计算的可扩展性更强。同时也可以衍生出很多很方便的计算方法。

  1. using System;
  2. using System.IO;
  3. namespace My_MD5
  4. {
  5.     class My_MD5
  6.     {
  7.         //static state variables
  8.         private static UInt32 A;
  9.         private static UInt32 B;
  10.         private static UInt32 C;
  11.         private static UInt32 D;
  12.         #region number of bits to rotate in tranforming
  13.         private const int S11 = 7;
  14.         private const int S12 = 12;
  15.         private const int S13 = 17;
  16.         private const int S14 = 22;
  17.         private const int S21 = 5;
  18.         private const int S22 = 9;
  19.         private const int S23 = 14;
  20.         private const int S24 = 20;
  21.         private const int S31 = 4;
  22.         private const int S32 = 11;
  23.         private const int S33 = 16;
  24.         private const int S34 = 23;
  25.         private const int S41 = 6;
  26.         private const int S42 = 10;
  27.         private const int S43 = 15;
  28.         private const int S44 = 21;
  29.         #endregion
  30.         #region F, G, H and I are basic MD5 functions
  31.         /* F, G, H and I are basic MD5 functions.
  32.         * 四个非线性函数:
  33.         *
  34.         * F(X,Y,Z) =(X&Y)|((~X)&Z)
  35.         * G(X,Y,Z) =(X&Z)|(Y&(~Z))
  36.         * H(X,Y,Z) =X^Y^Z
  37.         * I(X,Y,Z)=Y^(X|(~Z))
  38.         *
  39.         * (&与,|或,~非,^异或)
  40.         */
  41.         private static UInt32 F(UInt32 x, UInt32 y, UInt32 z)
  42.         {
  43.             return (x & y) | ((~x) & z);
  44.         }
  45.         private static UInt32 G(UInt32 x, UInt32 y, UInt32 z)
  46.         {
  47.             return (x & z) | (y & (~z));
  48.         }
  49.         private static UInt32 H(UInt32 x, UInt32 y, UInt32 z)
  50.         {
  51.             return x ^ y ^ z;
  52.         }
  53.         private static UInt32 I(UInt32 x, UInt32 y, UInt32 z)
  54.         {
  55.             return y ^ (x | (~z));
  56.         }
  57.         #endregion
  58.         #region FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4
  59.         /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
  60.         * Rotation is separate from addition to prevent recomputation.
  61.         */
  62.         private static void FF(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)
  63.         {
  64.             a = a + F(b, c, d) + mj + ti;
  65.             a = a << s | a >> (32 - s);
  66.             a += b;
  67.             // 转换为 :a=b+((a+F(b,c,d)+mj+ti)<<s)
  68.         }
  69.         private static void GG(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)
  70.         {
  71.             a = a + G(b, c, d) + mj + ti;
  72.             a = a << s | a >> (32 - s);
  73.             a += b;
  74.         }
  75.         private static void HH(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)
  76.         {
  77.             a = a + H(b, c, d) + mj + ti;
  78.             a = a << s | a >> (32 - s);
  79.             a += b;
  80.         }
  81.         private static void II(ref UInt32 a, UInt32 b, UInt32 c, UInt32 d, UInt32 mj, int s, UInt32 ti)
  82.         {
  83.             a = a + I(b, c, d) + mj + ti;
  84.             a = a << s | a >> (32 - s);
  85.             a += b;
  86.         }
  87.         #endregion
  88.         private static void MD5_Init()
  89.         {
  90.             A = 0x67452301; //in memory, this is 0x01234567
  91.             B = 0xefcdab89; //in memory, this is 0x89abcdef
  92.             C = 0x98badcfe; //in memory, this is 0xfedcba98
  93.             D = 0x10325476; //in memory, this is 0x76543210
  94.         }
  95.         private static void MD5_TrasformBlock(byte[] block)
  96.         {
  97.             UInt32 a, b, c, d;
  98.             UInt32[] x = new UInt32[16];
  99.             for(int i = 0, j = 0;i < 64;i += 4, j++)
  100.                 x[j] = (UInt32)(block[i] | block[i + 1] << 8 | block[i + 2] << 16 | block[i + 3] << 24);
  101.             a = A;
  102.             b = B;
  103.             c = C;
  104.             d = D;
  105.             /* Round 1 */
  106.             FF(ref a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
  107.             FF(ref d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
  108.             FF(ref c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
  109.             FF(ref b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
  110.             FF(ref a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
  111.             FF(ref d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
  112.             FF(ref c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
  113.             FF(ref b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
  114.             FF(ref a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
  115.             FF(ref d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
  116.             FF(ref c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  117.             FF(ref b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  118.             FF(ref a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  119.             FF(ref d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  120.             FF(ref c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  121.             FF(ref b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
  122.             /* Round 2 */
  123.             GG(ref a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
  124.             GG(ref d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
  125.             GG(ref c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  126.             GG(ref b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
  127.             GG(ref a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
  128.             GG(ref d, a, b, c, x[10], S22, 0x2441453); /* 22 */
  129.             GG(ref c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  130.             GG(ref b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
  131.             GG(ref a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
  132.             GG(ref d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  133.             GG(ref c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
  134.             GG(ref b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
  135.             GG(ref a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  136.             GG(ref d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
  137.             GG(ref c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
  138.             GG(ref b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
  139.             /* Round 3 */
  140.             HH(ref a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
  141.             HH(ref d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
  142.             HH(ref c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  143.             HH(ref b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  144.             HH(ref a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
  145.             HH(ref d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
  146.             HH(ref c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
  147.             HH(ref b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  148.             HH(ref a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  149.             HH(ref d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
  150.             HH(ref c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
  151.             HH(ref b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
  152.             HH(ref a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
  153.             HH(ref d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  154.             HH(ref c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  155.             HH(ref b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
  156.             /* Round 4 */
  157.             II(ref a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
  158.             II(ref d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
  159.             II(ref c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  160.             II(ref b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
  161.             II(ref a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  162.             II(ref d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
  163.             II(ref c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  164.             II(ref b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
  165.             II(ref a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
  166.             II(ref d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  167.             II(ref c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
  168.             II(ref b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  169.             II(ref a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
  170.             II(ref d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  171.             II(ref c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
  172.             II(ref b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
  173.             A += a;
  174.             B += b;
  175.             C += c;
  176.             D += d;
  177.         }
  178.         /// <summary>
  179.         /// 得到stream的md5
  180.         /// </summary>
  181.         /// <param name="stream">要处理的流</param>
  182.         /// <param name="index">开始处理的位置</param>
  183.         /// <param name="count">要处理的长度</param>
  184.         /// <returns></returns>
  185.         public static string MDStream(Stream stream, long index, long count)
  186.         {
  187.             if(stream == null)
  188.                 throw new ArgumentNullException();
  189.             byte[] block = new byte[64];
  190.             UInt64 size = 0;
  191.             int b = 0;
  192.             MD5_Init();
  193.             while(index-- > 0 && stream.ReadByte() >= 0)
  194.                 ;
  195.             if(index >= 0)
  196.                 throw new ArgumentException("""index");
  197.             while((b = stream.ReadByte()) != -1 && count-- > 0)
  198.             {
  199.                 block[size++ % 64] = (byte)b;
  200.                 if(size % 64 == 0)
  201.                     MD5_TrasformBlock(block);
  202.             }
  203.             if(count > 0)
  204.                 throw new ArgumentException("""count");
  205.             UInt64 bp = size % 64;//blockPoint
  206.             block[bp++] = 0x80;
  207.             if(bp > 56)
  208.             {
  209.                 while(bp < 64)
  210.                     block[bp++] = 0;
  211.                 MD5_TrasformBlock(block);
  212.                 for(int i = 0;i < 56;i++)
  213.                     block[i] = 0;
  214.             }
  215.             else
  216.                 while(bp < 56)
  217.                     block[bp++] = 0;
  218.             size *= 8;
  219.             block[56] = (byte)(size & 0xFF);
  220.             block[57] = (byte)((size >> 8) & 0xFF);
  221.             block[58] = (byte)((size >> 16) & 0xFF);
  222.             block[59] = (byte)((size >> 24) & 0xFF);
  223.             block[60] = (byte)((size >> 32) & 0xFF);
  224.             block[61] = (byte)((size >> 40) & 0xFF);
  225.             block[62] = (byte)((size >> 48) & 0xFF);
  226.             block[63] = (byte)(size >> 56);
  227.             MD5_TrasformBlock(block);
  228.             //return new UInt32[] { A, B, C, D };
  229.             return string.Format("{0}-{1}-{2}-{3}", BitConverter.ToString(BitConverter.GetBytes(A))
  230.                 , BitConverter.ToString(BitConverter.GetBytes(B))
  231.                 , BitConverter.ToString(BitConverter.GetBytes(C))
  232.                 , BitConverter.ToString(BitConverter.GetBytes(D))).Replace("-""");
  233.         }
  234.     }
  235. }


检测算法正确性的代码
用这段代码检测,只要出现了 OK!........说明我的算法是正确的。
  1. using System;
  2. using System.IO;
  3. using System.Security.Cryptography;
  4. namespace My_MD5
  5. {
  6.     class Program
  7.     {
  8.         static void Main(string[] args)
  9.         {
  10.             Random rnd = new Random();
  11.             MD5 md = MD5.Create();
  12.             bool f = true;
  13.             for(int i = 0;i < 10000;i++)
  14.             {
  15.                 byte[] buf = new byte[i];
  16.                 for(int j = 0;j < i;j++)
  17.                     buf[j] = (byte)rnd.Next(200);
  18.                 MemoryStream ms = new MemoryStream(buf);
  19.                 string s1 = My_MD5.MDStream(ms, 0, i);
  20.                 ms.Seek(0, SeekOrigin.Begin);
  21.                 string s2 = BitConverter.ToString(md.ComputeHash(ms)).Replace("-""");
  22.                 if(s1 != s2)
  23.                 {
  24.                     Console.WriteLine(i);
  25.                     f = false;
  26.                 }
  27.             }
  28.             if(f)
  29.                 Console.WriteLine("OK!........");
  30.         }
  31.     }
  32. }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值