zoukankan      html  css  js  c++  java
  • 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       }
  • 相关阅读:
    git命令上传项目到码云总结
    根据数组对象的某个属性值找到指定的元素
    Web前端开发规范文档
    在vue项目中安装使用Mint-UI
    字蛛fontSpider的使用
    vue 组件之间的数据传递
    ElasticStack系列之十 & 生产中的问题与解决方案
    ElasticStack系列之九 & master、data 和 client 节点
    ElasticStack系列之八 & _source 字段
    ElasticStack系列之七 & IK自动热更新原理与实现
  • 原文地址:https://www.cnblogs.com/aaaSoft/p/1533210.html
Copyright © 2011-2022 走看看