0

I wrote the following function to generate HMAC-SHA1 referring https://www.rfc-editor.org/rfc/rfc2104, however, the values I generate seem to differ from the values given on https://www.rfc-editor.org/rfc/rfc2202 and from what I've tested on https://www.freeformatter.com/hmac-generator.html.

For example, the function should be generating de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9 for text "The quick brown fox jumps over the lazy dog" with key "key", but it generates d3c446dbd70f5db3693f63f96a5931d49eaa5bab instead.

Could anyone point out my mistakes?

The function:

const int block_size = 64;
const int hash_output_size = 20;
const int ipadVal = 0x36;
const int opadVal = 0x5C;
std::string HMAC::getHMAC(const std::string &text)
{
// check if key length is block_size
// else, append 0x00 till the length of new key is block_size
int key_length = key.length();
std::string newkey = key;
if (key_length < block_size)
{
    int appended_zeros = block_size - key_length;
    // create new string with appended_zeros number of zeros
    std::string zeros = std::string(appended_zeros, '0');
    newkey = key + zeros;
}
if (key_length > block_size)
{
    SHA1 sha1;
    newkey = sha1(key);
}

// calculate hash of newkey XOR ipad and newkey XOR opad
std::string keyXipad = newkey;
std::string keyXopad = newkey;
for (int i = 0; i < 64; i++)
{
    keyXipad[i] ^= ipadVal;
    keyXopad[i] ^= opadVal;
}

// get first hash, hash of keyXipad+text
std::string inner_hash = getSHA1(keyXipad + text);

// get outer hash, hash of keyXopad+inner_hash
std::string outer_hash = getSHA1(keyXopad + inner_hash);

// return outer_hash
return outer_hash;
}

edit: In the line

std::string zeros = std::string(appended_zeros, '0');

'0' should be 0 instead : int instead of char. Thanks to @Igor Tandetnik for that.

Community
  • 1
  • 1
Magnus
  • 59
  • 6
  • Are you doing this just for education, or do you want to actually use your HMAC function somewhere? Because if it’s the latter, you really should find a library to do it for you. Either way, are you sure the `SHA1` class works correctly? – Daniel H Oct 06 '17 at 14:18
  • Just for education. I've tested the SHA1 with various values against online tools and it is working well. I even set up breakpoints and tested the values and their SHA1 values and all seemed correct. That's why I'm puzzled right now. – Magnus Oct 06 '17 at 14:23
  • 2
    `'0' != 0` .... – Igor Tandetnik Oct 06 '17 at 14:39
  • Okay...that was flaw. Thanks for that :D Output still not matching though. – Magnus Oct 07 '17 at 06:21

1 Answers1

0

Ok..so a little look around lead me to HMAC produces wrong results. Turns out, I was doing the same mistake of using hex as ascii.

I used a function to convert the inner_hash from hex to ascii and then everything turned out perfect.

The final version of the function:

std::string HMAC::getHMAC(const std::string &text)
{
// check if key length is block_size
// else, append 0x00 till the length of new key is block_size
int key_length = key.length();
std::string newkey = key;
if (key_length < block_size)
{
    int appended_zeros = block_size - key_length;
    // create new string with appended_zeros number of zeros
    std::cout << "\nAppending " << appended_zeros << " 0s to key";
    std::string zeros = std::string(appended_zeros, 0);
    newkey = key + zeros;
}
if (key_length > block_size)
{
    SHA1 sha1;
    newkey = sha1(key);
}

// calculate hash of newkey XOR ipad and newkey XOR opad
std::string keyXipad = newkey;
std::string keyXopad = newkey;
for (int i = 0; i < 64; i++)
{
    keyXipad[i] ^= ipadVal;
    keyXopad[i] ^= opadVal;
}

// get first hash, hash of keyXipad+text
std::string toInnerHash = keyXipad + text;
std::string inner_hash = getHash(toInnerHash);

// get outer hash, hash of keyXopad+inner_hash
std::string toOuterHash = keyXopad + hex_to_string(inner_hash);
std::string outer_hash = getHash(toOuterHash);

// return outer_hash
return outer_hash;
}

hex_to_string function taken from https://stackoverflow.com/a/16125797/3818617

Magnus
  • 59
  • 6