【问题标题】:How do I do a SHA1 File Checksum in C#?如何在 C# 中执行 SHA1 文件校验和?
【发布时间】:2010-12-31 22:08:33
【问题描述】:

如何使用文件上的SHA1CryptoServiceProvider() 来创建文件的 SHA1 校验和?

【问题讨论】:

    标签: c# .net sha1 checksum


    【解决方案1】:
    using (FileStream fs = new FileStream(@"C:\file\location", FileMode.Open))
    using (BufferedStream bs = new BufferedStream(fs))
    {
        using (SHA1Managed sha1 = new SHA1Managed())
        {
            byte[] hash = sha1.ComputeHash(bs);
            StringBuilder formatted = new StringBuilder(2 * hash.Length);
            foreach (byte b in hash)
            {
                formatted.AppendFormat("{0:X2}", b);
            }
        }
    }
    

    formatted 包含 SHA-1 哈希的字符串表示形式。此外,通过使用FileStream 而不是字节缓冲区,ComputeHash 以块的形式计算哈希,因此您不必一次性加载整个文件,这对大文件很有帮助。

    【讨论】:

    • 你应该使用StringBuilder,而不是在构建哈希字符串的过程中生成20个字符串。
    • StringBuilder 初始容量应该是哈希中字节数的两倍
    • 已编辑以反映 @MarkHeath 的评论并添加了 BufferedStream 以提高性能。
    • 我认为您不需要使用 BufferedStream。 stackoverflow.com/a/2069317/64334
    • 经过 100,000 次迭代测试,BufferedStream 没有任何区别,所以我将从示例中删除它。我还测试了另一种生成哈希字符串的方法,使用 BitConverter,它提供了中等 (6%) 的性能提升(以及更少的 LoC),因此在示例中也进行了修改。
    【解决方案2】:

    使用 ComputeHash 方法。见这里:

    ComputeHash

    示例 sn-p:

    using(var cryptoProvider = new SHA1CryptoServiceProvider())
    {
        string hash = BitConverter
                .ToString(cryptoProvider.ComputeHash(buffer));
    
        //do something with hash
    }
    

    其中缓冲区是文件的内容。

    【讨论】:

    • +1 获取有关使用 BitConverter 一次性生成十六进制字符串的重要提示。
    • SHA1CryptoServiceProvider 应该包含在 using 块中
    • BitConverter 用破折号 AA-F0-CC 分隔字节,这与 @mgbowen 的解决方案不同。可能是也可能不是我们想要的。
    【解决方案3】:

    如果您已经将文件作为流读取,则以下技术会在您读取文件时计算哈希值。唯一需要注意的是,您需要消耗整个流。

    class Program
        {
            static void Main(string[] args)
            {
                String sourceFileName = "C:\\test.txt";
                Byte[] shaHash;
    
                //Use Sha1Managed if you really want sha1
                using (var shaForStream = new SHA256Managed())
                using (Stream sourceFileStream = File.Open(sourceFileName, FileMode.Open))
                using (Stream sourceStream = new CryptoStream(sourceFileStream, shaForStream, CryptoStreamMode.Read))
                {
                    //Do something with the sourceStream 
                    //NOTE You need to read all the bytes, otherwise you'll get an exception ({"Hash must be finalized before the hash value is retrieved."}) 
                    while(sourceStream.ReadByte() != -1);                
                    shaHash = shaForStream.Hash;
                }
    
                Console.WriteLine(Convert.ToBase64String(shaHash));
            }
        }
    

    【讨论】:

    • +1 表示CryptoStream。如果您想从某个地方读取文件(例如:从 http 请求),将其写入某个地方(例如:磁盘上)并同时计算哈希,它可能会很有用。
    • 在对大文件进行测试时,此代码的性能比ComputeHash 解决方案差几个数量级。也许是ReadByte 一次阅读?
    • @MichaelKropat 很有趣。很高兴知道。 10 倍,100 倍慢?
    • @MichaelKropat - 只是想,如果开销是因为我的示例读取每个字节,那么如果您仍然使用流,那么这是没有意义的。
    【解决方案4】:

    你也可以试试:

    FileStream fop = File.OpenRead(@"C:\test.bin");
    string chksum = BitConverter.ToString(System.Security.Cryptography.SHA1.Create().ComputeHash(fop));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-14
      • 2021-05-02
      • 2013-04-05
      相关资源
      最近更新 更多