2

The 64 bytes are the same, but the == is returning false. I am guessing there may be something wrong with the encoding, but I can not figure out what I am doing wrong. Any ideas to fix this?

public static byte[] hashSHA512(string unhashedValue)
{
    SHA512 shaM = new SHA512Managed();
    byte[] hash = shaM.ComputeHash(Encoding.UTF8.GetBytes(unhashedValue));
    return hash;

}

public static bool Validate(string enteredValue, byte[] hashedValue)
{
    byte[] hash = hashSHA512 (enteredValue);
    return (hash == hashedValue);
}

I tested this with a simple value and since they both call the same hash method I do not see how it can fail other than something in the encoding. I am just using the built in System.Security.Cryptography.

stuartd
  • 70,509
  • 14
  • 132
  • 163
Jimmy
  • 175
  • 1
  • 3
  • 17

2 Answers2

6

In C#, two arrays are only equal to another if they are identical, i.e. they are the exact same array. The normal equality comparison will not check whether the contents of those arrays are equal:

byte[] x = new byte[] { 1, 2, 3 };
byte[] y = new byte[] { 1, 2, 3 };

Console.WriteLine(x == y); // false

You can use Enumerable.SequenceEqual to check whether the contents are equal:

Console.WriteLine(x.SequenceEqual(y)); // true

Since SHA512 hash sums are often displayed in hexadecimal, it might make sense for you to actually return a hexadecimal string instead of a byte array. You can use one of the many ways to convert a byte array into a hex string. And then, you can just perform an equality check on the string—which will work as you expect.

Community
  • 1
  • 1
poke
  • 369,085
  • 72
  • 557
  • 602
4

No, there's nothing wrong with the encoding - there is no encoding in a byte[]. They're just bytes. It's just a matter of == for arrays performing a reference comparison.

You could use SequenceEqual to compare the arrays:

public static bool Validate(string enteredValue, byte[] hashedValue)
{
    // TODO: Rename `hashSHA512 to follow .NET naming conventions
    byte[] hash = hashSHA512 (enteredValue);
    return hash.SequenceEqual(hashedValue);
}

Note that you'll need using System.Linq; in your using directives to bring in LINQ.

Alternatives:

  • Convert both to their base64 (text) representations and compare those
  • Write your own array equality checker, which could easily be more efficient than SequenceEqual
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Ok stupid moment for me. I actually thought about that but thought I was clear with == and did not even look into that. I guess I learned two things today, because I am using Xamarin and did not think LINQ was working in mono, but that fix works just fine even on a MAC. Thanks for the super fast help. – Jimmy Mar 24 '16 at 20:33
  • Yeah when you pointed out the reference equals I thought about creating an equality checker, but since I just needed a quick simple proof of concept skeleton the SequenceEqual was plenty fast. – Jimmy Mar 24 '16 at 20:44