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       }
  • 相关阅读:
    Java中四种引用类型
    使用VisualVM查看Java Heap Dump
    Java程序性能分析工具Java VisualVM(Visual GC)—程序员必备利器
    JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解
    设计模式2---建造者模式(Builder pattern)
    设计模式1---单例模式(Singleton pattern)
    移动端网络优化
    Http请求的 HttpURLConnection 和 HttpClient
    第四章 Activity和Activity调用栈分析 系统信息与安全机制 性能优化
    Android模块化编程之引用本地的aar
  • 原文地址:https://www.cnblogs.com/aaaSoft/p/1533210.html
Copyright © 2011-2022 走看看