C#中计算流指定位置和长度的MD5值

在Microsoft .NET Framework 2.0中,计算MD5值可以用到System.Security.Cryptography.MD5CryptoServiceProvider类,其计算MD5的方法ComputeHash()有三个重载方法。


名称说明

ComputeHash(Byte[])计算指定字节数组的哈希值。 (继承自 HashAlgorithm。)

ComputeHash(Stream)计算指定 Stream 对象的哈希值。 (继承自 HashAlgorithm。)

ComputeHash(Byte[], Int32, Int32)计算指定字节数组的指定区域的哈希值。 (继承自 HashAlgorithm。)

如果需要计算文件流中指定区域的哈希值(如大文件传输断点续传)时,这三个方法就不够用了,我们需要一个如下的重载方法:


名称说明

ComputeHash(Stream,Int32,Int32)计算指定 Stream 对象的指定区域的哈希值。(继承自 HashAlgorithm。)

  

不过微软并没有提供这个方法来计算流中指定区域的MD5值。通过反编译mscorlib.dll与查看微软公布的Framework部分源代码,发现Windows 2000 Professol与Windows XP及以上操作系统提供了一个 "Cryptdll.dll”,其中有3个关于计算MD5的API函数:

MD5Init

The MD5Init function initializes an MD5 message digest context. The context must be initialized for any new MD5 message digest. This function is defined by RSA.

void MD5Init(
MD5_CTX* context
);
 
 

MD5Update

The MD5Update function updates the MD5 context by using the supplied buffer for the message whose MD5 digest is being generated. This function is called for each buffer of the message being hashed. This function is defined by RSA.

void MD5Update(
MD5_CTX context,
unsigned char* input,
unsigned int inlen
);
 
 

MD5Final

The MD5Final function ends an MD5 message digest previously started by a call to the MD5Init function. Prior to calling MD5Final, use the MD5Update function to update the MD5 message digest context with each buffer in the message being hashed. This function is defined by RSA.

void MD5Final(
MD5_CTX context
);
有了这些准备,就可以实现计算流中指定区域的MD5值了,下面是MyMD5类的源代码:
 1         public   sealed   class  MyMD5 : HashAlgorithm
 2        {          [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet  =  System.Runtime.InteropServices.CharSet.Ansi)]
 3             public   struct  MD5_CTX
 4            {
 5                 ///  ULONG[2]              [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = System.Runtime.InteropServices.UnmanagedType.U4)]
 6                 public   uint [] i;
 7                 ///  ULONG[4]              [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = System.Runtime.InteropServices.UnmanagedType.U4)]
 8                 public   uint [] buf;
 9                 ///  unsigned char[64]              [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 64)]
10                 public   byte [] @in;
11                 ///  unsigned char[16]
12                [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst  =   16 )]
13                 public   byte [] digest;
14            }
15 
16            [DllImport( " cryptdll.dll " )]
17             public   static   extern   void  MD5Init( ref  MD5_CTX context);
18            [DllImport( " cryptdll.dll " )]
19             public   static   extern   void  MD5Update( ref  MD5_CTX context, Byte[] input, Int32 inlen);
20            [DllImport( " cryptdll.dll " )]
21             public   static   extern   void  MD5Final( ref  MD5_CTX context);
22 
23            MD5_CTX md5data  =   new  MD5_CTX();
24             protected   override   void  HashCore( byte [] array,  int  ibStart,  int  cbSize)
25            {
26                 if  (ibStart  !=   0 )
27                {
28                     byte [] tmparray  =   new   byte [cbSize  -  ibStart];
29                    array.CopyTo(tmparray, ibStart);
30                    array  =  tmparray;
31                }
32                MD5Update( ref  md5data, array, cbSize);
33            }
34 
35             protected   override   byte [] HashFinal()
36            {
37                MD5Final( ref  md5data);
38                 return  md5data.digest;
39            }
40 
41             public  MyMD5()
42            {
43                Initialize();
44            }
45             public   override   void  Initialize()
46            {
47                MD5Init( ref  md5data);
48            }
49 
50             public   byte [] ComputeHash(Stream inputStream,  int  offset,  long  count)
51            {
52                 int  num;
53                 long  totalHashCount  =   0 ;
54                inputStream.Seek(offset,SeekOrgin.Begin);//感谢denworld指正
55                 byte [] buffer  =   new   byte [ 0x1000 ];
56                 do
57                {
58                     int  readCount  =  buffer.Length;
59                     if  (count  -  totalHashCount  <  buffer.Length)
60                    {
61                        readCount  =  ( int )(count  -  totalHashCount);
62                    }
63                    num  =  inputStream.Read(buffer,  0 , readCount);
64                     if  (num  >   0 )
65                    {
66                         this .HashCore(buffer,  0 , num);
67                        totalHashCount  +=  num;
68                    }
69                }
70                 while  (num  >   0 );
71                 this .HashValue  =   this .HashFinal();
72                 byte [] buffer2  =  ( byte []) this .HashValue.Clone();
73                 this .Initialize();
74                 return  buffer2;
75            }
76        }

转载于:https://www.cnblogs.com/aaaSoft/archive/2009/07/28/1533210.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值