我有错误的哈希值? C#密码学

时间:2022-10-08 18:23:32

My text file says The quick brown fox jumps over the lazy dog, however when i try to get the hash from this file both the md5 and sha1 is different from the wikipedias result. I have 3 questions. 1) What did i do wrong in the code? 2) How can i have this piece of code better? (do i need the Initialize) 3) How do i salt this?

我的文本文件说快速的棕色狐狸跳过懒狗,但是当我尝试从这个文件中获取哈希值时,md5和sha1都与wikipedias结果不同。我有3个问题。 1)我在代码中做错了什么? 2)我怎样才能更好地使用这段代码? (我需要初始化)3)我如何加盐?

    {
        const int bufSize = 1024 * 8;
        int read;
        byte[] buf = new byte[bufSize];
        string fn = @"b.txt";
        byte[] result1 = new byte[0];
        byte[] result2 = new byte[0];
        SHA1 sha = new SHA1CryptoServiceProvider();
        MD5  md5 = new MD5CryptoServiceProvider();
        sha.Initialize();
        md5.Initialize();
        FileStream fin = File.OpenRead(fn);
        while ((read = fin.Read(buf, 0, buf.Length)) != 0)
        {
            result1 = sha.ComputeHash(buf);
            result2 = md5.ComputeHash(buf);
        }
        fin.Close();
        MessageBox.Show(myFunc(result1));
        MessageBox.Show(myFunc(result2));
    }

2 个解决方案

#1


(EDIT: Disposing of the hash algorithms now. I suspect it's unnecessary, but it's good practice :)

(编辑:现在处理哈希算法。我怀疑这是不必要的,但这是很好的做法:)

You're calling ComputeHash for the whole buffer even though you should only be hashing the portion of the buffer you've read. In addition, you're computing a new hash for each call to Read.

您正在为整个缓冲区调用ComputeHash,即使您只应该对已读取的缓冲区部分进行哈希处理。此外,您正在为每次调用Read计算一个新哈希。

Here's some really simple code to compute the hashes:

这里有一些非常简单的代码来计算哈希:

using System;
using System.IO;
using System.Security.Cryptography;

class Test
{
    static void Main()
    {
        byte[] plaintext = File.ReadAllBytes("b.txt");
        using (MD5 md5 = MD5.Create())
        {
            byte[] md5Hash = md5.ComputeHash(plaintext);
            Console.WriteLine(BitConverter.ToString(md5Hash));
        }

        using (SHA1 sha1 = SHA1.Create())
        {
            byte[] sha1Hash = sha1.ComputeHash(plaintext);
            Console.WriteLine(BitConverter.ToString(sha1Hash));
        }
    }
}

This gives the results as per wikipedia - note that b.txt shouldn't have a newline at the end of it.

这给出了*的结果 - 请注意,b.txt的末尾不应该有换行符。

An alternative way of getting the binary data to start with would be:

获取二进制数据的另一种方法是:

byte[] plaintext = Encoding.ASCII.GetBytes(
    "The quick brown fox jumps over the lazy dog");

Note that this is just the simple way of computing a hash in one go. If you want to do it in a streaming fashion (i.e. where you read some data, add it to the hash, read some more data etc) then either you can use the ComputeHash(Stream) overload or (if you want to "push" data to it) you can use TransformBlock and TransformFinalBlock, like this:

请注意,这只是一次计算哈希的简单方法。如果你想以流式方式(即你读取一些数据,将它添加到哈希,读取更多数据等),那么你可以使用ComputeHash(流)重载或(如果你想“推”)数据到它)你可以使用TransformBlock和TransformFinalBlock,如下所示:

using System.Text;

class Test
{
    static void Main()
    {
        using (MD5 md5 = MD5.Create())
        using (SHA1 sha1 = SHA1.Create())
        using (Stream input = File.OpenRead("b.txt"))
        {
            // Artificially small to make sure there's
            // more than one read
            byte[] buffer = new byte[4];
            int bytesRead;

            while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                md5.TransformBlock(buffer, 0, bytesRead, null, 0);
                sha1.TransformBlock(buffer, 0, bytesRead, null, 0);
            }
            md5.TransformFinalBlock(buffer, 0, 0);
            sha1.TransformFinalBlock(buffer, 0, 0);

            Console.WriteLine(BitConverter.ToString(md5.Hash));
            Console.WriteLine(BitConverter.ToString(sha1.Hash));
        }
    }
}

Note the way we pass null to TransformBlock because we don't need any output, and we don't transform any data in the final block. I suspect this is the example you'll want to use, based on your previous comments.

注意我们将null传递给TransformBlock的方式,因为我们不需要任何输出,并且我们不会转换最终块中的任何数据。我怀疑这是你想要使用的例子,基于你以前的评论。

#2


Regarding different results, it could depend on the character encoding you are using in your text, since these hash algorithms deal with bytes.

关于不同的结果,它可能取决于您在文本中使用的字符编码,因为这些哈希算法处理字节。

As far as improving your code, you are not disposing of your CryptoServiceProviders. Everything that inherits from HashAlgorithm implements IDisposable and needs to be disposed when you're finished with it, either by using using() or calling Dispose() directly. You're also not disposing of the FileStream, which has the same requirements regarding IDisposable.

至于改进代码,您不会丢弃CryptoServiceProviders。从HashAlgorithm继承的所有东西都实现了IDisposable,当你完成它时需要处理它,通过使用using()或直接调用Dispose()。您也没有处理FileStream,它对IDisposable有相同的要求。

#1


(EDIT: Disposing of the hash algorithms now. I suspect it's unnecessary, but it's good practice :)

(编辑:现在处理哈希算法。我怀疑这是不必要的,但这是很好的做法:)

You're calling ComputeHash for the whole buffer even though you should only be hashing the portion of the buffer you've read. In addition, you're computing a new hash for each call to Read.

您正在为整个缓冲区调用ComputeHash,即使您只应该对已读取的缓冲区部分进行哈希处理。此外,您正在为每次调用Read计算一个新哈希。

Here's some really simple code to compute the hashes:

这里有一些非常简单的代码来计算哈希:

using System;
using System.IO;
using System.Security.Cryptography;

class Test
{
    static void Main()
    {
        byte[] plaintext = File.ReadAllBytes("b.txt");
        using (MD5 md5 = MD5.Create())
        {
            byte[] md5Hash = md5.ComputeHash(plaintext);
            Console.WriteLine(BitConverter.ToString(md5Hash));
        }

        using (SHA1 sha1 = SHA1.Create())
        {
            byte[] sha1Hash = sha1.ComputeHash(plaintext);
            Console.WriteLine(BitConverter.ToString(sha1Hash));
        }
    }
}

This gives the results as per wikipedia - note that b.txt shouldn't have a newline at the end of it.

这给出了*的结果 - 请注意,b.txt的末尾不应该有换行符。

An alternative way of getting the binary data to start with would be:

获取二进制数据的另一种方法是:

byte[] plaintext = Encoding.ASCII.GetBytes(
    "The quick brown fox jumps over the lazy dog");

Note that this is just the simple way of computing a hash in one go. If you want to do it in a streaming fashion (i.e. where you read some data, add it to the hash, read some more data etc) then either you can use the ComputeHash(Stream) overload or (if you want to "push" data to it) you can use TransformBlock and TransformFinalBlock, like this:

请注意,这只是一次计算哈希的简单方法。如果你想以流式方式(即你读取一些数据,将它添加到哈希,读取更多数据等),那么你可以使用ComputeHash(流)重载或(如果你想“推”)数据到它)你可以使用TransformBlock和TransformFinalBlock,如下所示:

using System.Text;

class Test
{
    static void Main()
    {
        using (MD5 md5 = MD5.Create())
        using (SHA1 sha1 = SHA1.Create())
        using (Stream input = File.OpenRead("b.txt"))
        {
            // Artificially small to make sure there's
            // more than one read
            byte[] buffer = new byte[4];
            int bytesRead;

            while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                md5.TransformBlock(buffer, 0, bytesRead, null, 0);
                sha1.TransformBlock(buffer, 0, bytesRead, null, 0);
            }
            md5.TransformFinalBlock(buffer, 0, 0);
            sha1.TransformFinalBlock(buffer, 0, 0);

            Console.WriteLine(BitConverter.ToString(md5.Hash));
            Console.WriteLine(BitConverter.ToString(sha1.Hash));
        }
    }
}

Note the way we pass null to TransformBlock because we don't need any output, and we don't transform any data in the final block. I suspect this is the example you'll want to use, based on your previous comments.

注意我们将null传递给TransformBlock的方式,因为我们不需要任何输出,并且我们不会转换最终块中的任何数据。我怀疑这是你想要使用的例子,基于你以前的评论。

#2


Regarding different results, it could depend on the character encoding you are using in your text, since these hash algorithms deal with bytes.

关于不同的结果,它可能取决于您在文本中使用的字符编码,因为这些哈希算法处理字节。

As far as improving your code, you are not disposing of your CryptoServiceProviders. Everything that inherits from HashAlgorithm implements IDisposable and needs to be disposed when you're finished with it, either by using using() or calling Dispose() directly. You're also not disposing of the FileStream, which has the same requirements regarding IDisposable.

至于改进代码,您不会丢弃CryptoServiceProviders。从HashAlgorithm继承的所有东西都实现了IDisposable,当你完成它时需要处理它,通过使用using()或直接调用Dispose()。您也没有处理FileStream,它对IDisposable有相同的要求。