Hashing multiple byte[]'s together into a single hash with C#?
I have three fields: string Title
, byte[] Body
, and byte[] Data
, from which I want to calculate a single hash as a check to be sure they haven't been tampered with or corrupted.
In Python, I can use md5.update()
a few times in succession to perform this. But I can't find similar capability in C#. To use MD5.ComputeHash() I'd need to copy all my sources into a 开发者_StackOverflow中文版single byte[], which is a step I'd like to avoid.
How can I hash it all together into one hash without having to copy the data into a temporary buffer?
There is also solution in .Net Standard and .Net Core using IncrementalHash
IncrementalHash sha256 = IncrementalHash.CreateHash(HashAlgorithmName.SHA256)
// For each block:
sha256.AppendData(block);
// Get the hash code
byte[] hash = sha256.GetHashAndReset();
As pointed out by Eric Lippert, also use SHA256
instead of md5
for better collision resistence.
Almost all hash algorithms are designed in a way that they can successively be fed with the data in multiple blocks. The result is the same as if the whole data was hashed at once.
Create an instance of e.g. MD5CryptoServiceProvider and call the TransformBlock Method for each block and the TransformFinalBlock Method for the last block:
MD5 md5 = new MD5CryptoServiceProvider();
// For each block:
md5.TransformBlock(block, 0, block.Length, block, 0);
// For last block:
md5.TransformFinalBlock(block, 0, block.Length);
// Get the hash code
byte[] hash = md5.Hash;
Using plain .NET, I don't think there is a way to update and MD5 hash. However, Windows has an MD5Update function defined in crypt.dll. You could use Interop to leverage this I suppose.
Otherwise, there is an implementation of a PHP equivalent in .NET c#, located here on SO: Problem porting PHP crypt() function to C#
PS: I would definitely go for the combined temp variable solution :-)
Calling the ComputeHash function on three different values is going to create three different byte array results. Those results will then have to be combined in some way to produce a single hash. There is no way around this fact. It will create three new objects in the heap. It will compute a hash (a fairly slow operation) three times instead of just one.
I think the most performant way to do what you want is to just go ahead and copy your source values into a single byte array and take the hash of that.
You don't say why you want to avoid this approach. I think it wins in terms of simplicity and maintainability. It is the self-documenting, obvious approach. It is the most performant method. I don't really see a down-side.
you can create a Hash over the Hash values.
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] totalHash= md5.ComputeHash(md5.ComputeHash(part1).Concat(md5t.computeHash(part2)));
doesnt create a copy of the byte array but hashes a concatenation of the hashes.
You have to combine them all in a single variable and then calculate the MD5 Hash. I don't see any shortcut there.
You see, most of solutions proposed here just try either to run multiple commands on the same line ("one liners") or implement something to "under the hood" combine your fields and then Hash...
精彩评论