代码之家  ›  专栏  ›  技术社区  ›  sindre j

是否可以使用缓冲读取计算MD5(或其他)哈希?

  •  33
  • sindre j  · 技术社区  · 16 年前

    我需要计算相当大的文件(GB)的校验和。这可以使用以下方法完成:

        private byte[] calcHash(string file)
        {
            System.Security.Cryptography.HashAlgorithm ha = System.Security.Cryptography.MD5.Create();
            FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
            byte[] hash = ha.ComputeHash(fs);
            fs.Close();
            return hash;
        }
    

    类似这样的:(伪代码ish)

    byte [] hash = new byte [] { 0,0,0,0,0,0,0,0 };
    while(!eof)
    {
       buffer = readFromSourceFile();
       writefile(buffer);
       hash = calchash(buffer, hash);
    }
    

    哈希现在与在整个文件上运行calcHash函数所能实现的非常相似。

    5 回复  |  直到 16 年前
        1
  •  50
  •   Guffa    16 年前

    TransformBlock TransformFinalBlock 方法以块的形式处理数据。

    // Init
    MD5 md5 = MD5.Create();
    int offset = 0;
    
    // For each block:
    offset += md5.TransformBlock(block, 0, block.Length, block, 0);
    
    // For last block:
    md5.TransformFinalBlock(block, 0, block.Length);
    
    // Get the has code
    byte[] hash = md5.Hash;
    

    注意:它可以(至少与MD5提供程序一起)将所有块发送到 转换块 转换最终块 最后完成这个过程。

        2
  •  49
  •   pomeroy    15 年前

    我喜欢上面的答案,但为了完整性和更一般的解决方案,请参考 CryptoStream 标准接口 ,通过 HashAlgorithm 作为 ICryptoTransform 参数

    var file = new FileStream("foo.txt", FileMode.Open, FileAccess.Write);
    var md5 = MD5.Create();
    var cs = new CryptoStream(file, md5, CryptoStreamMode.Write);
    while (notDoneYet)
    {
        buffer = Get32MB();
        cs.Write(buffer, 0, buffer.Length);
    }
    System.Console.WriteLine(BitConverter.ToString(md5.Hash));
    

    在获取哈希之前,您可能必须关闭流(因此 哈希算法 我知道这已经完成了)。

        3
  •  5
  •   mafu    14 年前

    看来你可以用 TransformBlock TransformFinalBlock ,如本示例所示: Displaying progress updates when hashing large files

        4
  •  3
  •   Adam Liss    16 年前

    hash_init() -调用以分配资源并开始哈希。
    hash_update() -在新数据到达时调用。
    hash_final() -完成计算并释放资源。

    看看 http://www.openssl.org/docs/crypto/md5.html http://www.openssl.org/docs/crypto/sha.html 例如,C语言中的标准示例;我相信您的平台也有类似的库。

        5
  •  3
  •   Nick Randell    9 年前

    我刚刚不得不做一些类似的事情,但希望异步读取文件。它使用TransformBlock和TransformFinalBlock,并给出与Azure一致的答案,所以我认为它是正确的!

    private static async Task<string> CalculateMD5Async(string fullFileName)
    {
      var block = ArrayPool<byte>.Shared.Rent(8192);
      try
      {
         using (var md5 = MD5.Create())
         {
             using (var stream = new FileStream(fullFileName, FileMode.Open, FileAccess.Read, FileShare.Read, 8192, true))
             {
                int length;
                while ((length = await stream.ReadAsync(block, 0, block.Length).ConfigureAwait(false)) > 0)
                {
                   md5.TransformBlock(block, 0, length, null, 0);
                }
                md5.TransformFinalBlock(block, 0, 0);
             }
             var hash = md5.Hash;
             return Convert.ToBase64String(hash);
          }
       }
       finally
       {
          ArrayPool<byte>.Shared.Return(block);
       }
    }