2

All of this is new to me so please forgive my noobish question.

I'm trying to figure out HMAC step by step.

Let's say I have a following SHA-1 method:

public static string SHA_1(string input) 
{
    SHA1CryptoServiceProvider mySha = new SHA1CryptoServiceProvider();
    string temp = BitConverter.ToString(mySha.ComputeHash(Encoding.UTF8.GetBytes(input)));
    temp = temp.Replace("-", "").ToUpper();
    return temp;
} 

It receives a plain text string;

Let's say my secret key is "" (empty string) and so is the message; The HMAC is supposed to be: fbdb1d1b18aa6c08324b7d64b71fb76370690e1d

Now that's where I am a bit lost. I'll write down the steps as I understand them and please correct me if I am wrong (or where I am wrong rather).

  1. If the key is shorter than 64 bytes I need to pad it with 0's. So the padded key is 0x00 (x64 - because the key is empty, otherwise it's 64-key.Length);
  2. Two constants each 64 bytes long are:

ipad = 0x36 (x64)

opad = 0x5c (x64)

  1. because the key is empty string XOR results in the same opad and ipad, i.e.

ipad XOR key = ipad

opad XOR key = opad

  1. At this point all left to do is to compute the HMAC itself.

So: HMAC = Hash(opad || Hash(ipad || message)) and that should be it.

But I am not sure how to execute this. The message is a text string. opad and ipad are uint/byte arrays. I can convert them to ASCII as well and receive respectively:

ipad_str = "6666666666..." x64

opad_str = "\\\\\\\...." x64

Now my HMAC is supposed to be:

HMAC = SHA_1("\\\\\\...."+ SHA_1("6666666...."))

but the result doesn't match. Instead it is: 4DCF4B8D646EBD77EB704A9240BFA429078131A2

What am I missing here? Does the empty message have to be padded as well? I suspect that I misinterpret the concatenation, but I am not sure what other options I have. Should I leave ipad and opad as hex? SHA1 methods receives string so I must convert to some sort of a string, I just can't figure out what type exactly.

Any help would be greatly appreciated. Thanks in advance and Happy New Year!

B.K.
  • 9,982
  • 10
  • 73
  • 105
  • 5
    .NET has HMAC built in, you should use it. – Cory Nelson Dec 30 '15 at 04:27
  • I know it does. I am trying to understand the process, because I need to implement a custom HMAC for school project. – JNeverTells Dec 30 '15 at 04:36
  • Have you studied [rfc2104](https://tools.ietf.org/html/rfc2104)? – zaph Dec 30 '15 at 04:55
  • Usually you convert message string to bytes using a `Encoding.UTF8.GetBytes(message);` Also let's be clear that you understand the peusdocode `ipad || message` indicates concatenating/appending these, ***not*** OR/XOR: https://upload.wikimedia.org/wikipedia/commons/7/7f/SHAhmac.svg – AaronLS Dec 30 '15 at 05:02
  • 1
    Also, if you've implemented your own SHA_1, then ***check your intermediate results*** against known working SHA1 hash. For example, once you append ipad || message, use a builtin C# sha1 hash to verify that your `SHA_1()` and C#'s both produce the same result from that given input. At least then you narrow the possible problem areas. – AaronLS Dec 30 '15 at 05:06
  • Thanks guys. I have studied rfc2104, therefore I do think I understand the principles correctly. And yet the results are not consistent. So there must be a mistake in the way I understood them. – JNeverTells Dec 30 '15 at 12:08
  • The 'custom' SHA_1 is not really custom it uses managed ComputeHash, as you can see yourself. The only thing I added is the methods receives ASCII string rather than straight byte array. SHA_1 produces correct and consistent results, so the problem isn't there. – JNeverTells Dec 30 '15 at 12:11
  • And finally, of course I understand that || doesn't mean XOR/OR but appending. However, I found one problem in the way I tried to implement the verification. While appending opad and inner HASH I used the raw result of SHA_1 which is a hex string while opad is ASCII. But even when I convert the inner Hash to ASCII the result is still not consistent. I'll try to use byte array instead and see where this goes, I don't believe it would work though, because I am fairly certain the was no mistake in conversion process. – JNeverTells Dec 30 '15 at 12:15
  • The problem with my method was so obvious, it's not even funny. While appending the result of the opad and inner hash I left the inner hash in hex format but treated it as ASCII, as a result 104 bytes were send to the outer hash instead of 84. So the solution is something like: HMAC = SHA_1(opad + HexToASCII(SHA_1(ipad))); – JNeverTells Jan 02 '16 at 02:23
  • Of course. due to funkiness of the converters it's much better to work with byte arrays, but I just wanted to figure out where the things went wrong exactly. Can't believe I didn't see this immediately. Thanks for everyone who tried to help! Happy New Year! – JNeverTells Jan 02 '16 at 02:29

1 Answers1

2

The problem with my method was so obvious, it's not even funny. While appending the result of the opad and inner hash I left the inner hash in hex format but treated it as ASCII, as a result 104 bytes were sent to the outer hash instead of 84. So the solution is something like: HMAC = SHA_1(opad + HexToASCII(SHA_1(ipad)));