Frenz
Frenz

Reputation: 747

Whats the standard code to generate HMAC SHA256 with key using C#

I'd like to know if there is a standard code to generate a SHA256 hash using a key. I've come across several types of code, however, they don't generate the same output.

Code found at JokeCamp

private string CreateToken(string message, string secret)
{
  secret = secret ?? "";
  var encoding = new System.Text.ASCIIEncoding();
  byte[] keyByte = encoding.GetBytes(secret);
  byte[] messageBytes = encoding.GetBytes(message);
  using (var hmacsha256 = new HMACSHA256(keyByte))
  {
    byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
    return Convert.ToBase64String(hashmessage);
  }
}

Here's another one that I found

private static string ComputeHash(string apiKey, string message)
{
    var key = Encoding.UTF8.GetBytes(apiKey);
    string hashString;
    using (var hmac = new HMACSHA256(key))
    {
        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
        hashString = Convert.ToBase64String(hash);
    }

    return hashString;
 }

The code generated by both of these are different to what is generated by http://www.freeformatter.com/hmac-generator.html#ad-output

I'll be using the SHA256 for one of our external API's where consumers would hash the data and send it to us. So we just want to make sure we use a standard approach so that they send us the correct hash. Also, I would like to know if there are any well-known nugets for this. I've also tried to find a solution with Bouncy Castle, however, I couldn't find one that uses a key to hash.

Upvotes: 6

Views: 10256

Answers (2)

arboreal84
arboreal84

Reputation: 2154

They are almost equivalent.

The difference is how the encoding for the string is established.

In the first portion of code it assumes ASCII, whereas in the second portion it assumes UTF-8. It is possible that the string used another encoding which is none of those.

But regardless of that, the idea is to understand what is the goal of this operation. The truly relevant things in this context are:

  1. Given equal input, output should be the same
  2. There should be no way to retrieve the plaintext only by knowing the output (within a reasonable amount of time)
  3. After hashing, you no longer require the original input in plaintext.

A secure cryptographic hashing function (meaning not older functions like MD5) achieves that.

Then, if your data store where hashes are stored is compromised, the attacker would only have a hash which cannot be used to retrieved the original plaintext. This is why hashing is used rather than encryption, encryption is a reversible operation (through decryption).

Then, within the system, if you've made the decision to use one encoding, you need to keep that decision consistent across all components in your system so they can interoperate.

Upvotes: 1

BobbyTables
BobbyTables

Reputation: 4685

The difference is because of the character encodings (ASCII vs UTF-8 in your examples). Note that the hashing algorithm takes an array of bytes, and you do the conversion from a string to that byte-array beforehand.

Your question "whats the standard code" probably hasnt an answer, id say that if you expect the input to contain content from just the ASCII character-space, go for that, if not go for UTF-8. Either way - communicate it to your users

If you want to look at it from a usability perspective and make it the optimal for your users - go for both. Hash the content both ways and check agains the users incoming hash, but it all depends on your evaluation on clock-cycles vs security vs usability (you can have two)

Upvotes: 3

Related Questions