.NET中HashAlgorithm搭配CryptoStream未生成哈希的问题排查
问题分析与解决
你的代码问题出在未触发哈希算法的最终计算步骤,以及对哈希值的错误字符串转换方式,具体如下:
核心问题
哈希算法实现的ICryptoTransform是一种特殊的加密变换:它不会将输入数据直接传递到目标流,而是积累输入数据用于计算哈希值。只有在完成所有输入处理后(调用FlushFinalBlock()或CryptoStream被释放),才会将最终的哈希值写入到目标流中。
你的代码在调用cs.Write(fileBytes)后直接读取ms.ToArray(),此时CryptoStream还未完成哈希计算,也没有将哈希值写入MemoryStream,导致你错误地获取到原输入数据(实际是因为你误解了哈希变换与CryptoStream的配合逻辑)。
另外,用Encoding.UTF8.GetString(hashBytes)转换哈希值是错误的——哈希值是二进制字节序列,并非UTF-8编码的文本,直接转换会导致乱码或错误的字符串表示。
修正后的代码
public static void HashFilesUsingCryptoStream(string inputPath) { var fileBytes = File.ReadAllBytes(inputPath); using ICryptoTransform hashAlg = SHA1.Create(); using var ms = new MemoryStream(); using var cs = new CryptoStream(ms, hashAlg, CryptoStreamMode.Write); cs.Write(fileBytes); cs.FlushFinalBlock(); // 关键:触发哈希计算,并将最终哈希值写入MemoryStream var hashBytes = ms.ToArray(); Console.WriteLine($"Number of Bytes in Hash algorithms: {hashBytes.Length}"); // 正确转换哈希值为十六进制字符串 Console.WriteLine("Hash: " + BitConverter.ToString(hashBytes).Replace("-", "")); }
另一种实现方式(利用using块的释放逻辑)
你也可以将读取MemoryStream的代码放在CryptoStream的using块外部,因为using块结束时会自动调用Dispose(),而Dispose()内部会自动调用FlushFinalBlock():
public static void HashFilesUsingCryptoStream(string inputPath) { var fileBytes = File.ReadAllBytes(inputPath); using ICryptoTransform hashAlg = SHA1.Create(); byte[] hashBytes; using (var ms = new MemoryStream()) { using (var cs = new CryptoStream(ms, hashAlg, CryptoStreamMode.Write)) { cs.Write(fileBytes); } // cs释放时自动完成哈希计算并写入ms hashBytes = ms.ToArray(); } Console.WriteLine($"Number of Bytes in Hash algorithms: {hashBytes.Length}"); Console.WriteLine("Hash: " + BitConverter.ToString(hashBytes).Replace("-", "")); }
内容的提问来源于stack exchange,提问作者Mehdi Mowlavi
相关产品推荐
相关产品推荐

